chore: remove claude-product-cycle directory (#3061)

This commit is contained in:
Rajan Maurya 2026-01-07 15:34:34 +05:30 committed by GitHub
parent fd1525e032
commit 145ab0cf7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
359 changed files with 326 additions and 87606 deletions

View File

@ -0,0 +1,207 @@
# /project-add - Add New Project (Interactive)
Create a new project workspace with the 5-layer structure.
## Usage
```
/project-add # Interactive project creation
/project-add "project-name" # Create with specified name
```
## Instructions
### Step 1: Gather Project Info
If no name provided, ask:
```markdown
## New Project Setup
Please provide:
1. **Project Name** (lowercase, hyphenated): e.g., `my-app`, `fineract-client`
2. **Project Type**: Android | iOS | KMP | Web
3. **Description**: Brief project description
```
### Step 2: Create Workspace Structure
```bash
# Create workspace directory
mkdir -p claude-product-cycle/workspaces/{{PROJECT_NAME}}
# Create 6 layer directories
mkdir -p claude-product-cycle/workspaces/{{PROJECT_NAME}}/design-spec-layer/features
mkdir -p claude-product-cycle/workspaces/{{PROJECT_NAME}}/server-layer/endpoints
mkdir -p claude-product-cycle/workspaces/{{PROJECT_NAME}}/client-layer
mkdir -p claude-product-cycle/workspaces/{{PROJECT_NAME}}/feature-layer
mkdir -p claude-product-cycle/workspaces/{{PROJECT_NAME}}/platform-layer
mkdir -p claude-product-cycle/workspaces/{{PROJECT_NAME}}/testing-layer
```
### Step 3: Create PROJECT.md
Create `workspaces/{{PROJECT_NAME}}/PROJECT.md`:
```markdown
# {{PROJECT_NAME}}
**Type**: {{PROJECT_TYPE}}
**Created**: {{DATE}}
**Description**: {{DESCRIPTION}}
---
## Quick Start
```bash
/project-set {{PROJECT_NAME}} # Activate this project
/gap-analysis # Check status
/design [feature] # Start designing
```
---
## Structure
```
workspaces/{{PROJECT_NAME}}/
├── PROJECT.md # This file
├── design-spec-layer/ # Feature specifications
│ └── features/ # Per-feature specs
├── server-layer/ # API documentation
│ └── endpoints/ # Per-endpoint docs
├── client-layer/ # Network/data layer tracking
├── feature-layer/ # UI layer tracking
├── platform-layer/ # Platform-specific tracking
└── testing-layer/ # Test tracking
```
---
## Status
| Layer | Progress | Next Action |
|-------|:--------:|-------------|
| Design | 0% | `/design [feature]` |
| Server | 0% | Document APIs |
| Client | 0% | `/client [feature]` |
| Feature | 0% | `/feature [feature]` |
| Platform | 0% | Platform setup |
```
### Step 4: Create Layer Index Files
**design-spec-layer/STATUS.md**:
```markdown
# Design Layer Status
**Project**: {{PROJECT_NAME}}
**Last Updated**: {{DATE}}
## Features
| Feature | SPEC | MOCKUP | API | STATUS | Complete |
|---------|:----:|:------:|:---:|:------:|:--------:|
| (none yet) | - | - | - | - | - |
---
**Next**: Run `/design [feature]` to add first feature
```
**client-layer/LAYER_STATUS.md**:
```markdown
# Client Layer Status
**Project**: {{PROJECT_NAME}}
**Last Updated**: {{DATE}}
## Services
| Service | Repository | Models | DI | Complete |
|---------|:----------:|:------:|:--:|:--------:|
| (none yet) | - | - | - | - |
```
**feature-layer/LAYER_STATUS.md**:
```markdown
# Feature Layer Status
**Project**: {{PROJECT_NAME}}
**Last Updated**: {{DATE}}
## Features
| Feature | ViewModel | Screen | Navigation | DI | Complete |
|---------|:---------:|:------:|:----------:|:--:|:--------:|
| (none yet) | - | - | - | - | - |
```
### Step 5: Optionally Set Active
Ask user:
```markdown
## Project Created
**Name**: {{PROJECT_NAME}}
**Location**: `workspaces/{{PROJECT_NAME}}/`
Would you like to set this as the active project?
1. **Yes** - Set active and start working
2. **No** - Keep current project active
```
If yes:
```bash
echo "{{PROJECT_NAME}}" > claude-product-cycle/ACTIVE_PROJECT
```
### Step 6: Show Completion
```markdown
## Project Created Successfully
**Project**: {{PROJECT_NAME}}
**Workspace**: `workspaces/{{PROJECT_NAME}}/`
**Active**: {{IS_ACTIVE}}
---
### Structure Created
```
workspaces/{{PROJECT_NAME}}/
├── PROJECT.md ✅
├── design-spec-layer/ ✅
│ ├── STATUS.md ✅
│ └── features/ ✅
├── server-layer/ ✅
│ └── endpoints/ ✅
├── client-layer/ ✅
│ └── LAYER_STATUS.md ✅
├── feature-layer/ ✅
│ └── LAYER_STATUS.md ✅
├── platform-layer/ ✅
└── testing-layer/ ✅
```
---
### Next Steps
1. `/project-set {{PROJECT_NAME}}` - Activate (if not active)
2. `/design [feature]` - Create first feature spec
3. `/gap-analysis` - View project status
---
**Ready to build!**
```
## Output Rules
1. Create complete workspace structure
2. Initialize all index/status files
3. Ask before setting as active
4. Show clear next steps

View File

@ -0,0 +1,48 @@
# /project-list - List All Projects
List all available projects in the multi-project workspace.
## Usage
```
/project-list # List all projects
```
## Instructions
### Step 1: Read Workspaces
```bash
ls claude-product-cycle/workspaces/
```
### Step 2: Get Active Project
```bash
cat claude-product-cycle/ACTIVE_PROJECT
```
### Step 3: Display Project List
```markdown
## Available Projects
| # | Project | Status | Path |
|:-:|---------|:------:|------|
{{PROJECT_ROWS}}
**Active**: {{ACTIVE_PROJECT}}
---
### Commands
- `/project-set [name]` - Switch to a project
- `/project-add` - Add new project
```
## Output Rules
1. List all directories in workspaces/
2. Mark active project with arrow (→)
3. Show path to each workspace

View File

@ -0,0 +1,67 @@
# /project-set - Set Active Project
Switch the active project for all commands.
## Usage
```
/project-set mifos-mobile # Switch to mifos-mobile project
/project-set test-project # Switch to test-project
```
## Instructions
### Step 1: Validate Project Exists
```bash
ls claude-product-cycle/workspaces/{{PROJECT_NAME}}/
```
If directory doesn't exist, show error:
```markdown
## Error: Project Not Found
Project `{{PROJECT_NAME}}` does not exist.
**Available projects**:
{{PROJECT_LIST}}
Run `/project-add` to create a new project.
```
### Step 2: Update ACTIVE_PROJECT
```bash
echo "{{PROJECT_NAME}}" > claude-product-cycle/ACTIVE_PROJECT
```
### Step 3: Confirm Switch
```markdown
## Project Switched
**Active Project**: {{PROJECT_NAME}}
**Workspace**: `workspaces/{{PROJECT_NAME}}/`
---
### Project Summary
| Layer | Status |
|-------|:------:|
| Design | {{DESIGN_STATUS}} |
| Server | {{SERVER_STATUS}} |
| Client | {{CLIENT_STATUS}} |
| Feature | {{FEATURE_STATUS}} |
| Platform | {{PLATFORM_STATUS}} |
---
**Next**: Run `/gap-analysis` to see current status
```
## Output Rules
1. Validate project exists before switching
2. Update ACTIVE_PROJECT file
3. Show project summary after switch

View File

@ -23,13 +23,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
/session-end # Save context for next session /session-end # Save context for next session
``` ```
### Key Context Files ### Claude Product Cycle Framework
| File | Purpose | This project uses the [claude-product-cycle](https://github.com/mobilebytesensei/claude-product-cycle) framework for AI-assisted development.
|------|---------|
| `claude-product-cycle/CURRENT_WORK.md` | Active work, next actions | **Workspace**: [mifos-x-claude-cycle-workspaces](https://github.com/therajanmaurya/mifos-x-claude-cycle-workspaces)
| `claude-product-cycle/PRODUCT_MAP.md` | Master status tracker |
| `design-spec-layer/features/*/STATUS.md` | Per-feature status |
### 5-Layer Lifecycle ### 5-Layer Lifecycle

View File

@ -1,611 +0,0 @@
# Claude Product Cycle - Mifos Mobile
> **Vision**: AI-powered development framework for structured feature implementation
> **Project**: Mifos Mobile - Self-Service Banking Application (KMP)
> **Backend**: Apache Fineract Self-Service APIs
> **Created**: 2025-12-26
---
## Project Overview
Mifos Mobile is a Kotlin Multiplatform (KMP) application for financial institutions. It provides end-users with the ability to manage their accounts (Loan, Savings, Shares), beneficiaries, transfers, and view transactions. The application consumes the Apache Fineract Self-Service API.
### Tech Stack
- **Frontend**: Kotlin Multiplatform (Android, iOS, Desktop, Web)
- **UI**: Jetpack Compose Multiplatform
- **Architecture**: MVI (Model-View-Intent) with Clean Architecture
- **DI**: Koin
- **Networking**: Ktor + Ktorfit
- **Backend**: Apache Fineract (External API - not managed by this project)
---
## The Big Picture
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLAUDE PRODUCT CYCLE FRAMEWORK │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ DEVELOPMENT CYCLE │ │
│ │ │ │
│ │ /projectstatus → See where you are │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ /design [Feature] → Architect the feature (Opus) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ /implement [Feature] → Full E2E implementation │ │
│ │ │ │ │
│ │ │ OR use layer commands: │ │
│ │ │ /client [Feature] → Network + Data layers │ │
│ │ │ /feature [Feature] → UI layer (ViewModel + Screen) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ /verify [Feature] → Validate implementation vs spec │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## Framework Components
### Directory Structure
```
claude-product-cycle/
├── CLAUDE_PRODUCT_CYCLE.md # This file - master documentation
├── COMMANDS.md # Quick command reference
├── commands-layer/ # Slash commands for Claude Code
│ ├── design.md # /design - Architecture phase
│ ├── implement.md # /implement - E2E implementation
│ ├── client.md # /client - Network + Data layers
│ ├── feature.md # /feature - UI layer
│ ├── verify.md # /verify - Validation
│ └── projectstatus.md # /projectstatus - Overview
├── design-spec-layer/ # Feature specifications
│ ├── STATUS.md # Single source of truth for all features
│ ├── _shared/ # Shared patterns and guides
│ │ ├── PATTERNS.md # Implementation patterns
│ │ └── API_REFERENCE.md # Fineract API quick reference
│ └── features/ # Individual feature bundles
│ └── [feature]/
│ ├── SPEC.md # What to build (UI, flows)
│ ├── API.md # APIs needed
│ └── STATUS.md # Feature implementation status
└── server-layer/ # Backend documentation
└── FINERACT_API.md # Fineract Self-Service API docs
```
---
## Command Reference
| Command | Phase | Purpose | Model |
|---------|-------|---------|-------|
| `/projectstatus` | Any | See project status, all commands | Any |
| `/design [Feature]` | Design | Create SPEC.md + API.md (architecture) | **Opus** |
| `/implement [Feature]` | Build | Full feature implementation (all layers) | Sonnet |
| `/client [Feature]` | Build | Network + Data + Domain layers | Sonnet |
| `/feature [Feature]` | Build | UI layer (ViewModel + Screen) | Sonnet |
| `/verify [Feature]` | QA | Validate implementation vs spec | Sonnet |
---
## Architecture Layers
### 1. Network Layer (`core/network/`)
**Purpose**: API communication with Fineract Self-Service endpoints
```kotlin
// Service interface using Ktorfit
interface ClientService {
@GET(ApiEndPoints.CLIENTS)
fun clients(): Flow<Page<Client>>
@GET(ApiEndPoints.CLIENTS + "/{clientId}/accounts")
fun getClientAccounts(@Path("clientId") clientId: Long): Flow<ClientAccounts>
}
```
**Key Components**:
- `services/` - Ktorfit service interfaces
- `utils/ApiEndPoints.kt` - API endpoint constants
- `di/NetworkModule.kt` - DI registration
### 2. Data Layer (`core/data/`)
**Purpose**: Repository implementations, data transformations
```kotlin
interface HomeRepository {
fun clientAccounts(clientId: Long): Flow<DataState<ClientAccounts>>
fun currentClient(clientId: Long): Flow<DataState<Client>>
}
```
**Key Components**:
- `repository/` - Repository interfaces and implementations
- `di/DataModule.kt` - DI registration
### 3. Feature Layer (`feature/[name]/`)
**Purpose**: UI presentation with MVI architecture
```kotlin
// ViewModel with State, Event, Action pattern
class HomeViewModel(
private val homeRepository: HomeRepository,
) : BaseViewModel<HomeState, HomeEvent, HomeAction>(initialState) {
override fun handleAction(action: HomeAction) { ... }
}
// Immutable UI State
@Immutable
data class HomeState(
val clientAccounts: ClientAccounts? = null,
val uiState: HomeScreenState = HomeScreenState.Loading,
)
// One-time Events (navigation, toasts)
sealed interface HomeEvent {
data class Navigate(val route: String) : HomeEvent
}
// User Actions
sealed interface HomeAction {
data object Retry : HomeAction
data class OnNavigate(val route: String) : HomeAction
}
```
**Key Components**:
- `[Feature]ViewModel.kt` - MVI ViewModel
- `[Feature]Screen.kt` - Compose UI
- `components/` - Reusable composables
- `navigation/` - Navigation definition
- `di/[Feature]Module.kt` - DI registration
---
## Feature Catalog
| Feature | Module | Status | APIs |
|---------|--------|--------|------|
| Auth (Login/Register) | `feature:auth` | Done | authentication, registration |
| Home Dashboard | `feature:home` | Done | clients, accounts |
| Accounts Overview | `feature:accounts` | Done | clients/accounts |
| Savings Account | `feature:savings-account` | Done | savingsaccounts |
| Loan Account | `feature:loan-account` | Done | loans |
| Share Account | `feature:share-account` | Done | shareaccounts |
| Beneficiary | `feature:beneficiary` | Done | beneficiaries/tpt |
| Transfer | `feature:transfer-process` | Done | accounttransfers |
| Third Party Transfer | `feature:third-party-transfer` | Done | beneficiaries, accounttransfers |
| Recent Transactions | `feature:recent-transaction` | Done | savingsaccounts/transactions |
| Notifications | `feature:notification` | Done | notifications |
| Client Charges | `feature:client-charge` | Done | clients/charges |
| Guarantor | `feature:guarantor` | Done | loans/guarantors |
| QR Code | `feature:qr` | Done | - (local) |
| Settings | `feature:settings` | Done | user |
| Passcode | `feature:passcode` | Done | - (local) |
| Location | `feature:location` | Done | - (external maps) |
---
## Fineract Self-Service API Overview
Base URL: `https://{server}/fineract-provider/api/v1/self/`
### Core Endpoints
| Category | Endpoint | Methods |
|----------|----------|---------|
| Authentication | `authentication` | POST |
| Registration | `registration` | POST, GET |
| Clients | `clients` | GET |
| Savings | `savingsaccounts` | GET, POST, PUT |
| Loans | `loans` | GET, POST, PUT |
| Shares | `shareaccounts` | GET, POST |
| Beneficiaries | `beneficiaries/tpt` | GET, POST, PUT, DELETE |
| Transfers | `accounttransfers` | GET, POST |
| User | `user` | GET, PUT |
---
## Development Workflow
### 1. Design Phase (`/design [Feature]`)
```
1. Read existing code and understand current implementation
2. Create/update SPEC.md with:
- ASCII mockups
- User interactions
- State model
- API requirements
3. Create/update API.md with endpoint details
4. Update STATUS.md
```
### 2. Implementation Phase (`/implement [Feature]`)
```
1. Git: Create feature branch
2. Validate: Check dependencies
3. Client Layer:
- Create/update DTOs in core/network/model/
- Create/update Service in core/network/services/
- Create/update Repository in core/data/repository/
- Register in DI modules
4. Feature Layer:
- Create/update ViewModel
- Create/update Screen
- Create/update Components
- Register navigation
- Register in DI module
5. Build & Test: ./gradlew build
6. Lint: ./gradlew spotlessApply detekt
7. Commit with conventional commits
```
### 3. Verification Phase (`/verify [Feature]`)
```
1. Compare SPEC.md vs actual code
2. Check all user actions implemented
3. Check all API calls present
4. Verify DI registration
5. Check navigation
6. Report gaps
```
---
## Patterns
### MVI ViewModel Pattern
```kotlin
class FeatureViewModel(
private val repository: FeatureRepository,
) : BaseViewModel<FeatureState, FeatureEvent, FeatureAction>(
initialState = FeatureState()
) {
override fun handleAction(action: FeatureAction) {
when (action) {
is FeatureAction.Load -> loadData()
is FeatureAction.Retry -> retry()
}
}
private fun loadData() {
viewModelScope.launch {
repository.getData()
.collect { dataState ->
when (dataState) {
is DataState.Loading -> updateState { it.copy(isLoading = true) }
is DataState.Success -> updateState {
it.copy(isLoading = false, data = dataState.data)
}
is DataState.Error -> updateState {
it.copy(isLoading = false, error = dataState.message)
}
}
}
}
}
}
```
### Repository Pattern
```kotlin
class FeatureRepositoryImpl(
private val service: FeatureService,
) : FeatureRepository {
override fun getData(): Flow<DataState<Data>> = flow {
emit(DataState.Loading)
try {
val result = service.fetchData().first()
emit(DataState.Success(result))
} catch (e: Exception) {
emit(DataState.Error(e.message ?: "Unknown error"))
}
}
}
```
### Screen Pattern
```kotlin
@Composable
fun FeatureScreen(
viewModel: FeatureViewModel = koinViewModel(),
onNavigateBack: () -> Unit,
) {
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
// Handle one-time events
LaunchedEffect(Unit) {
viewModel.eventFlow.collect { event ->
when (event) {
is FeatureEvent.NavigateBack -> onNavigateBack()
}
}
}
FeatureContent(
state = state,
onAction = viewModel::sendAction,
)
}
```
---
## Cross-Update Rules
After ANY implementation:
1. Update feature's `STATUS.md`
2. Update main `claude-product-cycle/design-spec-layer/STATUS.md`
3. Add changelog entries
4. Run `./gradlew build` to verify
---
## Getting Started
This section provides everything you need to effectively use the Claude Product Cycle framework.
### Prerequisites
Before starting, ensure you have:
| Requirement | Details |
|-------------|---------|
| Claude Code CLI | Anthropic's CLI tool with slash command support |
| Project Access | Clone of `mifos-mobile` repository |
| Branch | Work from `development` or feature branches |
| Fineract Server | Access to demo: `gsoc.mifos.community` (demo credentials in CLAUDE.md) |
### Session Workflow
Always use session commands to maintain context across conversations:
```
┌─────────────────────────────────────────────────────────────────┐
│ SESSION WORKFLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ /session-start # Load context from previous │
│ │ # session (CURRENT_WORK.md) │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ DO YOUR WORK │ # Use gap-analysis, design, │
│ │ • /gap-analysis │ # implement, verify commands │
│ │ • /design │ │
│ │ • /implement │ │
│ │ • /verify │ │
│ └─────────────────────┘ │
│ │ │
│ ▼ │
│ /session-end # Save context for next session │
│ # (updates CURRENT_WORK.md) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 5-Layer Lifecycle
Every feature flows through 5 layers:
```
┌─────────────────────────────────────────────────────────────────┐
│ 5-LAYER LIFECYCLE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Layer 1: DESIGN │
│ ├── SPEC.md → What to build (screens, flows) │
│ ├── MOCKUP.md → How it looks (ASCII/visual mockups) │
│ ├── API.md → What APIs needed (endpoints, payloads) │
│ └── STATUS.md → Implementation progress │
│ │
│ Layer 2: SERVER │
│ └── Fineract API → External API availability check │
│ │
│ Layer 3: CLIENT │
│ ├── Network → core/network/services/*Service.kt │
│ ├── Data → core/data/repository/*Repository.kt │
│ └── Model → core/network/model/*.kt │
│ │
│ Layer 4: FEATURE │
│ ├── ViewModel → feature/*/viewmodel/*ViewModel.kt │
│ ├── Screen → feature/*/screens/*Screen.kt │
│ ├── Navigation → feature/*/navigation/*Navigation.kt │
│ └── DI → feature/*/di/*Module.kt │
│ │
│ Layer 5: PLATFORM │
│ ├── Android → cmp-android/ │
│ ├── iOS → cmp-ios/ │
│ ├── Desktop → cmp-desktop/ │
│ └── Web → cmp-web/ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### Gap Analysis & Planning
Use these commands to understand what's done vs what's needed:
```bash
# Quick overview - all layers summary
/gap-analysis
# Layer-specific analysis
/gap-analysis design # Design specs, mockups, API docs status
/gap-analysis server # Fineract API availability
/gap-analysis client # Network services, repositories status
/gap-analysis feature # ViewModels, Screens status
/gap-analysis platform # Platform-specific builds status
# Sub-section analysis
/gap-analysis design mockup # Mockup generation status only
/gap-analysis design spec # Specification status only
/gap-analysis client network # Network services only
/gap-analysis feature auth # Single feature status
# Feature-specific (all 5 layers for one feature)
/gap-analysis auth # Auth feature across all layers
/gap-analysis transfer # Transfer feature across all layers
# Plan improvements
/gap-planning auth # Generate plan to fill gaps for auth
/gap-planning design mockup # Plan for mockup generation
```
### Design Layer Workflow
The design layer has 4 sub-sections per feature:
```
features/[name]/
├── SPEC.md # WHAT to build
│ ├── Feature Overview
│ ├── User Stories
│ ├── Screen Descriptions
│ ├── User Flows
│ └── State Management
├── MOCKUP.md # HOW it looks
│ ├── ASCII Mockups (all screens)
│ ├── Component Breakdown
│ ├── Interaction Patterns
│ └── Data Binding Reference → References API.md
├── API.md # WHAT APIs (Single Source of Truth)
│ ├── Endpoints Required
│ ├── Request/Response Schemas
│ ├── Error Responses
│ └── Dependencies
└── STATUS.md # Progress tracking
├── Design Phase (%)
├── Client Phase (%)
├── Feature Phase (%)
└── Platform Phase (%)
```
**Generating Mockups**:
```bash
# Generate mockups for a feature
/design auth # Opens design workflow
# Then select "mockup" sub-section when prompted
```
### Implementation Workflow
```bash
# Full E2E implementation (all layers)
/implement auth
# OR layer-by-layer implementation
/client auth # Network + Data layers only
/feature auth # UI layer only (requires client layer)
# After implementation
/verify auth # Validate against spec
```
**Implementation Order**:
```
1. /design [feature] → Create specifications
2. /implement [feature] → Full implementation
- OR -
2a. /client [feature] → Network + Repository
2b. /feature [feature] → ViewModel + Screen
3. /verify [feature] → Validate completeness
```
### Common Scenarios
#### Scenario 1: Start New Feature
```bash
/session-start # Load previous context
/gap-analysis # See what's missing
/design new-feature # Create specs (uses Opus model)
/implement new-feature # Implement E2E
/verify new-feature # Validate
/session-end # Save context
```
#### Scenario 2: Fix Gaps in Existing Feature
```bash
/session-start
/gap-analysis auth # Find gaps in auth feature
/gap-planning auth # Get action plan
/implement auth # Fill the gaps
/verify auth
/session-end
```
#### Scenario 3: Update Mockups Only
```bash
/session-start
/gap-analysis design mockup # See which mockups are missing
/design auth # Then choose mockup sub-section
/session-end
```
#### Scenario 4: Check Before PR
```bash
/session-start
/gap-analysis # Full project overview
/verify [feature] # Verify your changes
./ci-prepush.sh # Run pre-push checks
/session-end
```
### Key Context Files
| File | Purpose | When to Check |
|------|---------|---------------|
| `CURRENT_WORK.md` | Active work, next actions | Start of session |
| `PRODUCT_MAP.md` | Master status tracker | Project overview |
| `design-spec-layer/STATUS.md` | Design layer progress | Before design work |
| `features/*/STATUS.md` | Per-feature progress | Before feature work |
### Quick Reference
| Task | Command |
|------|---------|
| See project status | `/projectstatus` |
| Find gaps | `/gap-analysis` or `/gap-analysis [layer]` |
| Plan improvements | `/gap-planning [feature]` |
| Design a feature | `/design [feature]` |
| Implement E2E | `/implement [feature]` |
| Client layer only | `/client [feature]` |
| UI layer only | `/feature [feature]` |
| Validate work | `/verify [feature]` |
| Start session | `/session-start` |
| End session | `/session-end` |
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-26 | Initial framework setup for Mifos Mobile |

View File

@ -1,135 +0,0 @@
# Claude Product Cycle - Commands Reference
## Quick Reference
```
┌─────────────────────────────────────────────────────────────────────┐
│ DESIGN PHASE │
├─────────────────────────────────────────────────────────────────────┤
│ /design [Feature] → Create SPEC.md + API.md (Opus) │
├─────────────────────────────────────────────────────────────────────┤
│ IMPLEMENT PHASE │
├─────────────────────────────────────────────────────────────────────┤
│ /implement [Feature] → Full E2E implementation (Sonnet) │
│ │
│ OR use layer commands independently: │
│ /client [Feature] → Network + Data layers │
│ /feature [Feature] → UI layer (ViewModel + Screen) │
├─────────────────────────────────────────────────────────────────────┤
│ VERIFY PHASE │
├─────────────────────────────────────────────────────────────────────┤
│ /verify [Feature] → Validate implementation vs spec │
├─────────────────────────────────────────────────────────────────────┤
│ UTILITIES │
├─────────────────────────────────────────────────────────────────────┤
│ /projectstatus → Project overview │
└─────────────────────────────────────────────────────────────────────┘
```
---
## Command Details
### `/projectstatus`
Shows the current state of all features, implementation progress, and suggested next steps.
**Usage**: `/projectstatus`
---
### `/design [Feature]`
Creates or updates the feature specification (SPEC.md + API.md). Best used with Opus for complex architectural decisions.
**Usage**:
```
/design → Show feature list
/design Home → Full spec review/create for Home
/design Accounts add filter → Add specific section
```
**Output**: Creates/updates in `claude-product-cycle/design-spec-layer/features/[feature]/`
---
### `/implement [Feature]`
Full end-to-end implementation including client layer (Network + Data) and feature layer (UI).
**Usage**:
```
/implement → Show feature status list
/implement Home → Full implementation
/implement Home --quick → Skip validations
```
**Pipeline**:
1. Git: Create feature branch
2. Validate: Check dependencies
3. Client: Network + Data layers
4. Feature: ViewModel + Screen
5. Build & Test
6. Lint & Format
7. Commit
---
### `/client [Feature]`
Implements only the client layer (Network + Data + Domain).
**Usage**: `/client Home`
**Creates**:
- DTOs in `core/network/model/`
- Services in `core/network/services/`
- Repository in `core/data/repository/`
- DI module registrations
---
### `/feature [Feature]`
Implements only the feature/UI layer.
**Usage**: `/feature Home`
**Creates**:
- ViewModel in `feature/[name]/`
- Screen composable
- Components
- Navigation
- DI module
---
### `/verify [Feature]`
Validates that the implementation matches the specification.
**Usage**: `/verify Home`
**Checks**:
- SPEC.md vs actual code
- All user actions implemented
- All API calls present
- DI registration complete
- Navigation configured
---
## Feature List
| Feature | Command |
|---------|---------|
| Authentication | `/design auth` |
| Home Dashboard | `/design home` |
| Accounts | `/design accounts` |
| Loan Account | `/design loan-account` |
| Savings Account | `/design savings-account` |
| Share Account | `/design share-account` |
| Beneficiary | `/design beneficiary` |
| Transfer | `/design transfer` |
| Recent Transactions | `/design recent-transaction` |
| Notifications | `/design notification` |
| Settings | `/design settings` |
| Passcode | `/design passcode` |
| Guarantor | `/design guarantor` |
| QR Code | `/design qr` |
| Location | `/design location` |
| Client Charges | `/design client-charge` |

View File

@ -1,211 +0,0 @@
# Current Work
**Last Updated**: 2026-01-05
**Branch**: feature/design-specifications
**Session Note**: Phase 4 Complete - core:testing module created with fakes, fixtures, TestTags
---
## Active Tasks
| # | Task | Feature | Status | Files | Notes |
|---|------|---------|:------:|-------|-------|
| 1 | Command Rewrite | implement | ✅ Done | .claude/commands/implement.md | O(1) + Pattern Detection |
| 2 | Command Rewrite | client | ✅ Done | .claude/commands/client.md | O(1) + Pattern Detection |
| 3 | Command Rewrite | feature | ✅ Done | .claude/commands/feature.md | O(1) + TestTags |
| 4 | Command Rewrite | verify | ✅ Done | .claude/commands/verify.md | O(1) + Gap Detection |
| 5 | Command Rewrite | design | ✅ Done | .claude/commands/design.md | O(1) + Mockup Status |
| 6 | Command Rewrite | verify-tests | ✅ Done | .claude/commands/verify-tests.md | O(1) + Test Status |
| 7 | Design Token Integration | feature | ✅ Done | .claude/commands/feature.md | Phase 3.5 Token Integration |
| 8 | Design Tokens Index | design-spec | ✅ Done | DESIGN_TOKENS_INDEX.md | O(1) token lookup |
| 9 | Test Stub Generation | implement | ✅ Done | .claude/commands/implement.md | Phase 5: Auto-generate tests |
| 10 | TestTag Validation | verify | ✅ Done | .claude/commands/verify.md | Enhanced TestTag checks |
| 11 | Test Stubs Guide | docs | ✅ Done | TEST_STUBS_GUIDE.md | TDD reference |
| 12 | core:testing Module | testing | ✅ Done | core/testing/ | Fakes, fixtures, TestTags |
| 13 | Mockup Generation | home | ⏳ Next | features/home/mockups/ | Run `/design home mockup` |
| 14 | v2.0 UI Implementation | dashboard | Planned | feature/dashboard/ | After mockups done |
---
## In Progress
### Phase 1, 2 & 3 Complete: Commands + Design Integration + Testing Automation
**All 6 core commands now use O(1 lookup pattern**:
| Command | Index Files Used | Key Features |
|---------|------------------|--------------|
| `/implement` | FEATURE_MAP, MODULES_INDEX, SCREENS_INDEX | Pattern detection, TestTags |
| `/client` | FEATURE_MAP, API_INDEX | Service/Repository patterns |
| `/feature` | MODULES_INDEX, SCREENS_INDEX, DESIGN_TOKENS_INDEX | MVI pattern, TestTags, **Token Integration** |
| `/verify` | FEATURES_INDEX, FEATURE_MAP, MODULES_INDEX, SCREENS_INDEX, API_INDEX | Gap detection, verification scoring |
| `/design` | FEATURES_INDEX, MOCKUPS_INDEX, API_INDEX | Mockup status, tool selection |
| `/verify-tests` | TESTING_STATUS.md (all layers), MODULES_INDEX | Test dashboard, coverage tracking |
**Phase 2: Design Token Integration**:
- Created `DESIGN_TOKENS_INDEX.md` for O(1) token lookup
- Added Phase 3.5 to `/feature` command
- Supports both Google Stitch and MD3 token formats
- Auto-generates `${Feature}Theme.kt` with gradients/colors
- Auto-generates `${Feature}Animations.kt` if animations defined
- Maps tokens to existing `DesignToken` system
**Features with Design Tokens**: 8/17
- ✅ auth (google-stitch) - gradients, animations
- ✅ dashboard (md3) - components
- ✅ settings, guarantor, qr, passcode, location, client-charge (md3)
**Phase 3: Testing Automation**:
- Added Phase 5 to `/implement` command for test stub generation
- Enhanced `/verify` command with TestTag validation
- Created `TEST_STUBS_GUIDE.md` documentation
- Auto-generates: ViewModel tests, Screen tests, Fake repositories
- Validates: TestTag naming convention (`feature:component:id`)
- Supports TDD workflow: Red → Green → Refactor
**Testing Layer (6th Layer)**:
- Created `testing-layer/` with O(1) index files
- `LAYER_STATUS.md` - Test coverage dashboard (17 features)
- `TEST_PATTERNS.md` - ViewModel, Screen, Fake, Integration, Screenshot patterns
- `TEST_TAGS_INDEX.md` - TestTag specifications for all features
- `TEST_FIXTURES_INDEX.md` - Test fixture inventory
- `FAKE_REPOS_INDEX.md` - Fake repository inventory
- `patterns/` - Detailed pattern files (viewmodel-test.md, screen-test.md, etc.)
- `templates/` - Code templates (.kt.template files)
**Phase 4: core:testing Module** (NEW):
- Enabled `core:testing` in settings.gradle.kts
- Created KMP module with commonMain/androidMain source sets
- **TestTags**: Complete tags for all 17 features (auth, home, accounts, etc.)
- **Fake Repositories**: FakeUserAuthRepository, FakeHomeRepository, FakeAccountsRepository, FakeBeneficiaryRepository, FakeTransferRepository, FakeNotificationRepository
- **Test Fixtures**: UserFixture, ClientAccountsFixture, BeneficiaryFixture
- **Test Utils**: MainDispatcherRule, FlowTestExtensions, TestCoroutineExtensions
- **DI Module**: TestModule for Koin test setup
- Module compiles successfully ✅
---
## Design Layer - Phase 2: Mockup Generation
**Progress**: 2/17 features (12%)
- ✅ dashboard - mockups generated
- ✅ auth - mockups generated
- ⏳ home - next
- ⏳ 14 more features pending
**Commands**:
```
/gap-analysis design mockup # See mockup progress (2/17)
/gap-planning design mockup # Step-by-step plan
/design [feature] mockup # Generate mockups for feature
```
---
## Recently Completed
| Date | Task | Feature | Outcome |
|------|------|---------|---------|
| 2026-01-05 | core:testing Module | core/testing/ | Fakes, fixtures, TestTags - compiles ✅ |
| 2026-01-05 | /gap-status command | commands | Plan progress tracking |
| 2026-01-05 | Testing Layer (6th Layer) | testing-layer/ | Full O(1) test infrastructure |
| 2026-01-05 | Phase 3: Testing Automation | implement/verify | Test stubs + TestTag validation |
| 2026-01-05 | TEST_STUBS_GUIDE.md | docs | TDD reference documentation |
| 2026-01-05 | Phase 2: Design Token Integration | feature | Phase 3.5 + DESIGN_TOKENS_INDEX.md |
| 2026-01-05 | Command Rewrite | verify | O(1) + Gap Detection + Verification Score |
| 2026-01-05 | Command Rewrite | design | O(1) + Mockup Status + Tool Selection |
| 2026-01-05 | Command Rewrite | verify-tests | O(1) + Test Dashboard + Coverage Tracking |
| 2026-01-05 | Command Rewrite | implement | O(1) + Pattern Detection + TestTags |
| 2026-01-05 | Command Rewrite | client | O(1) + Pattern Detection |
| 2026-01-05 | Command Rewrite | feature | O(1) + Pattern Detection + TestTags |
| 2026-01-03 | Auth mockups | auth | Generated PROMPTS.md + design-tokens.json |
| 2026-01-03 | MCP integration | design | Added tool selection, installed stitch-ai |
| 2026-01-03 | Commands README | commands | Full reference with all sub-commands |
| 2026-01-03 | Sub-section support | gap-analysis | Added {layer} {sub-section} syntax |
---
## Quick Context for Next Session
### Key Files to Read
1. This file (`CURRENT_WORK.md`)
2. `.claude/commands/implement.md` - E2E implementation with **Phase 5 Test Stubs**
3. `.claude/commands/feature.md` - Feature layer with **Phase 3.5 Token Integration**
4. `.claude/commands/verify.md` - Verification with O(1) + **TestTag Validation**
5. `.claude/commands/design.md` - Design with O(1) + Mockup Status
6. `.claude/commands/verify-tests.md` - Test verification with O(1)
7. `TEST_STUBS_GUIDE.md` - TDD test stub reference
8. `core/testing/` - **NEW** Testing module with fakes, fixtures, TestTags
9. `design-spec-layer/DESIGN_TOKENS_INDEX.md` - O(1) token lookup
10. `client-layer/FEATURE_MAP.md` - Service/Repository mapping
11. `feature-layer/MODULES_INDEX.md` - Module inventory
12. `feature-layer/SCREENS_INDEX.md` - Screen inventory
### Key Commands
- `/session-start` - Load this context
- `/gap-analysis` - Quick overview of all layers
- `/implement [feature]` - Full E2E implementation (updated)
- `/client [feature]` - Client layer only (updated)
- `/feature [feature]` - Feature layer only (updated)
- `/verify [feature]` - Verify implementation vs spec
### O(1) Index Files (Core Context)
| File | Purpose | Lines |
|------|---------|:-----:|
| FEATURE_MAP.md | Service → Feature mapping | ~170 |
| MODULES_INDEX.md | All feature modules | ~115 |
| SCREENS_INDEX.md | All 63 screens | ~270 |
| API_INDEX.md | All API endpoints | ~400 |
| FEATURES_INDEX.md | All 17 features | ~100 |
| DESIGN_TOKENS_INDEX.md | **NEW** Design tokens per feature | ~150 |
### Architecture Notes
- KMP: Android, iOS, Desktop, Web
- DI: Koin modules per feature
- Navigation: Jetbrains Compose Navigation
- Network: Ktorfit services
- State: MVI pattern (State, Event, Action)
- Testing: TestTags pattern (feature:component:id)
---
## Resume Instructions
1. Run `/session-start` to load context
2. Run `/gap-analysis` to see current status
3. Test new commands:
- `/implement` - Should show feature list with O(1 lookup
- `/client [feature]` - Should show service/repo status
- `/feature [feature]` - Should show module/screen status
4. Continue mockup generation with `/design home mockup`
5. Eventually test full E2E with `/implement [new-feature]`
---
## Session History
| Date | Focus | Outcome |
|------|-------|---------|
| 2026-01-05 | Phase 4: core:testing Module | Created core/testing/ with fakes, fixtures, TestTags ✅ |
| 2026-01-05 | Testing Layer (6th Layer) | Created testing-layer/ with O(1 indexes, patterns, templates |
| 2026-01-05 | Phase 3: Testing Automation | Test stubs in /implement, TestTag validation in /verify |
| 2026-01-05 | Phase 2: Design-Code Integration | Token integration in /feature, DESIGN_TOKENS_INDEX.md |
| 2026-01-05 | Phase 1: Command Rewrite | All 6 core commands now O(1): verify, design, verify-tests |
| 2026-01-05 | Command rewrite | /implement, /client, /feature with O(1) + patterns |
| 2026-01-03 | Mockup generation | Auth mockups done, MCP integrated, 2/17 complete |
| 2026-01-03 | Command refactoring | Created template system, 5-layer structure |
---
## What's Next
1. **Write First Tests**: Use `core:testing` module to write ViewModel tests for auth feature
2. **Continue Mockups**: Generate mockups for remaining 15 features (`/design home mockup`)
3. **Dashboard Feature**: After mockups, implement new dashboard
4. **Phase 5: Session Persistence** (gap-planning roadmap)
- Intelligent session checkpoints
- Context continuity across restarts
5. **Phase 6: Documentation Integration** (gap-planning roadmap)
- Auto-generate README updates
- Architecture diagram generation
6. **Migration**: Move claude-product-cycle to separate repo (after validation)

View File

@ -1,560 +0,0 @@
# Claude Product Cycle - Template Migration Plan
## Overview
Move claude-product-cycle architecture to `kmp-project-template` so all derived projects inherit the framework while maintaining project-specific implementations.
---
## Current State
```
kmp-project-template/ # Base template (no claude-product-cycle)
├── mifos-mobile/ # Has full claude-product-cycle
├── mobile-wallet/ # No claude-product-cycle
├── android-client/ # No claude-product-cycle
└── mifos-x-group-banking/ # No claude-product-cycle
```
## Target State
```
kmp-project-template/
├── .claude/
│ └── commands/ # Framework commands (parameterized)
├── claude-product-cycle/
│ ├── _templates/ # Reusable templates
│ ├── _framework/ # Architecture documentation
│ └── PROJECT_SETUP.md # How to configure for a project
├── mifos-mobile/ # Extends template
│ └── claude-product-cycle/
│ ├── design-spec-layer/ # Project-specific specs
│ ├── server-layer/ # Project-specific APIs
│ ├── client-layer/ # Project-specific mappings
│ ├── feature-layer/ # Project-specific features
│ └── platform-layer/ # Project-specific platforms
```
---
## Architecture Decision
### What Goes in Template (Reusable)
| Component | Purpose | Sync Strategy |
|-----------|---------|---------------|
| Commands Framework | `/gap-analysis`, `/gap-planning`, etc. | Override in projects |
| Layer Templates | SPEC.md, API.md structure | Copy on init |
| Index Templates | FEATURES_INDEX.md structure | Generate per project |
| Testing Framework | Test patterns, TestTag system | Inherit |
| Architecture Docs | 5-layer lifecycle, patterns | Reference |
### What Stays in Projects (Specific)
| Component | Purpose | Example |
|-----------|---------|---------|
| Feature Specs | SPEC.md content | "Login with biometrics" |
| API Documentation | Actual endpoints | `/self/authentication` |
| Mockups | UI designs | Figma links, tokens |
| Implementation Status | Progress tracking | ✅/⚠️/❌ per feature |
| Feature List | Project features | auth, home, transfer... |
---
## Proposed Directory Structure
### Template Repository (`kmp-project-template`)
```
kmp-project-template/
├── .claude/
│ ├── commands/
│ │ ├── gap-analysis.md # Parameterized framework
│ │ ├── gap-planning.md # Parameterized framework
│ │ ├── design.md # Parameterized framework
│ │ ├── implement.md # Parameterized framework
│ │ ├── verify.md # Parameterized framework
│ │ ├── verify-tests.md # Parameterized framework
│ │ ├── session-start.md # Session management
│ │ ├── session-end.md # Session management
│ │ └── projectstatus.md # Project overview
│ └── settings.json # Default Claude settings
├── claude-product-cycle/
│ ├── _framework/
│ │ ├── 5-LAYER-LIFECYCLE.md # Architecture overview
│ │ ├── O1-LOOKUP-PATTERN.md # Index file strategy
│ │ ├── COMMAND-REFERENCE.md # All commands explained
│ │ └── TESTING-STRATEGY.md # TDD approach
│ │
│ ├── _templates/
│ │ ├── design-spec-layer/
│ │ │ ├── FEATURES_INDEX.template.md
│ │ │ ├── MOCKUPS_INDEX.template.md
│ │ │ ├── TESTING_STATUS.template.md
│ │ │ └── feature/
│ │ │ ├── SPEC.template.md
│ │ │ ├── API.template.md
│ │ │ └── STATUS.template.md
│ │ │
│ │ ├── server-layer/
│ │ │ ├── API_INDEX.template.md
│ │ │ ├── API_REFERENCE.template.md
│ │ │ ├── TESTING_STATUS.template.md
│ │ │ └── endpoints/
│ │ │ └── CATEGORY.template.md
│ │ │
│ │ ├── client-layer/
│ │ │ ├── FEATURE_MAP.template.md
│ │ │ ├── LAYER_STATUS.template.md
│ │ │ └── TESTING_STATUS.template.md
│ │ │
│ │ ├── feature-layer/
│ │ │ ├── MODULES_INDEX.template.md
│ │ │ ├── SCREENS_INDEX.template.md
│ │ │ ├── LAYER_STATUS.template.md
│ │ │ └── TESTING_STATUS.template.md
│ │ │
│ │ ├── platform-layer/
│ │ │ ├── LAYER_STATUS.template.md
│ │ │ ├── TESTING_STATUS.template.md
│ │ │ └── platforms/
│ │ │ ├── ANDROID.template.md
│ │ │ ├── IOS.template.md
│ │ │ ├── DESKTOP.template.md
│ │ │ └── WEB.template.md
│ │ │
│ │ └── gap-analysis/
│ │ ├── dashboard.template.md
│ │ └── layer-*.template.md
│ │
│ ├── PROJECT_CONFIG.md # How to configure
│ ├── SYNC_GUIDE.md # How to sync updates
│ └── CHANGELOG.md # Version history
└── CLAUDE.md # References claude-product-cycle
```
### Derived Project (`mifos-mobile`, `mobile-wallet`, etc.)
```
mifos-mobile/
├── .claude/
│ ├── commands/ # Can override template commands
│ │ └── custom-command.md # Project-specific commands
│ └── settings.json # Project-specific settings
├── claude-product-cycle/
│ ├── PROJECT.md # Project identity & config
│ │ - name: "Mifos Mobile"
│ │ - type: "Self-Service Banking"
│ │ - features: [auth, home, accounts, ...]
│ │ - api_base: "https://server/fineract-provider/api/v1/self/"
│ │
│ ├── design-spec-layer/
│ │ ├── FEATURES_INDEX.md # Generated from template
│ │ ├── MOCKUPS_INDEX.md # Project-specific content
│ │ ├── STATUS.md
│ │ ├── TESTING_STATUS.md
│ │ └── features/
│ │ ├── auth/
│ │ │ ├── SPEC.md # Project-specific
│ │ │ ├── API.md # Project-specific
│ │ │ ├── STATUS.md
│ │ │ └── mockups/
│ │ ├── home/
│ │ └── ... (all project features)
│ │
│ ├── server-layer/
│ │ ├── API_INDEX.md # Project-specific endpoints
│ │ ├── API_REFERENCE.md
│ │ ├── TESTING_STATUS.md
│ │ └── endpoints/ # Project-specific
│ │
│ ├── client-layer/
│ │ ├── FEATURE_MAP.md # Project-specific mappings
│ │ ├── LAYER_STATUS.md
│ │ └── TESTING_STATUS.md
│ │
│ ├── feature-layer/
│ │ ├── MODULES_INDEX.md # Project-specific modules
│ │ ├── SCREENS_INDEX.md # Project-specific screens
│ │ ├── LAYER_STATUS.md
│ │ └── TESTING_STATUS.md
│ │
│ └── platform-layer/
│ ├── LAYER_STATUS.md # Project-specific
│ ├── TESTING_STATUS.md
│ └── platforms/
└── CLAUDE.md # Project-specific instructions
```
---
## Project Configuration (`PROJECT.md`)
Each derived project has a `PROJECT.md` that configures the framework:
```markdown
# Project Configuration
## Identity
| Key | Value |
|-----|-------|
| name | Mifos Mobile |
| type | Self-Service Banking |
| repo | openMF/mifos-mobile |
| template_version | 1.0.0 |
## API Configuration
| Key | Value |
|-----|-------|
| base_url | https://{server}/fineract-provider/api/v1/self/ |
| auth_type | Basic + Tenant Header |
| demo_server | tt.mifos.community |
| demo_user | maria / password |
## Features
| # | Feature | Design Dir | Feature Dir |
|:-:|---------|------------|-------------|
| 1 | auth | features/auth/ | feature/auth/ |
| 2 | home | features/home/ | feature/home/ |
| ... | ... | ... | ... |
## Platforms
| Platform | Module | Status |
|----------|--------|--------|
| Android | cmp-android | Primary |
| iOS | cmp-ios | CocoaPods |
| Desktop | cmp-desktop | JVM |
| Web | cmp-web | Experimental |
```
---
## Command Parameterization
Commands in template read from `PROJECT.md` to adapt behavior:
### Template Command (gap-analysis.md)
```markdown
# Gap Analysis Command
## Instructions
### Step 0: Read Project Config
Read `claude-product-cycle/PROJECT.md` to get:
- Feature list
- API base URL
- Platform configuration
### Step 1: Read O(1) Index Files
[... rest of command using project config ...]
```
### Override Mechanism
Projects can override commands by creating same file in `.claude/commands/`:
```
Template: kmp-project-template/.claude/commands/gap-analysis.md
Override: mifos-mobile/.claude/commands/gap-analysis.md (takes precedence)
```
---
## Sync Strategy
### Option A: Git Subtree (Recommended)
```bash
# In derived project, add template as subtree
git subtree add --prefix=claude-product-cycle/_framework \
https://github.com/openMF/kmp-project-template.git \
main --squash
# Pull updates from template
git subtree pull --prefix=claude-product-cycle/_framework \
https://github.com/openMF/kmp-project-template.git \
main --squash
```
**Pros**:
- Single repo, no submodule complexity
- Can modify locally if needed
- Easy to pull updates
**Cons**:
- Subtree history can get messy
- Manual pull required
### Option B: Git Submodule
```bash
# Add template as submodule
git submodule add https://github.com/openMF/kmp-project-template.git \
claude-product-cycle/_framework
# Update submodule
git submodule update --remote
```
**Pros**:
- Clear separation
- Explicit versioning
**Cons**:
- Submodule complexity
- Extra clone steps
### Option C: Copy + Version Tag (Simplest)
```bash
# Copy template files on setup
cp -r kmp-project-template/claude-product-cycle/_framework/ \
mifos-mobile/claude-product-cycle/_framework/
# Track version in PROJECT.md
template_version: 1.0.0
```
**Pros**:
- Simplest to understand
- No git complexity
**Cons**:
- Manual sync
- Can diverge
### Recommendation: Option A (Git Subtree)
Best balance of simplicity and maintainability.
---
## Migration Steps
### Phase 1: Prepare Template (Week 1)
1. **Create framework docs in template**
```bash
mkdir -p kmp-project-template/claude-product-cycle/_framework
mkdir -p kmp-project-template/claude-product-cycle/_templates
```
2. **Extract reusable content from mifos-mobile**
- Copy command files to template
- Parameterize hardcoded values
- Create template files with `{{PLACEHOLDER}}`
3. **Create PROJECT_CONFIG.md template**
4. **Test in template repo**
### Phase 2: Migrate mifos-mobile (Week 2)
1. **Restructure claude-product-cycle**
```bash
# Move framework to _framework/
# Keep project-specific in layer folders
```
2. **Create PROJECT.md with mifos-mobile config**
3. **Update commands to read from PROJECT.md**
4. **Verify all commands work**
### Phase 3: Rollout to Other Projects (Week 3-4)
1. **mobile-wallet (mifos-pay)**
- Clone template structure
- Create PROJECT.md
- Generate initial index files
- Add feature specs
2. **android-client (field officer)**
- Same process
3. **mifos-x-group-banking**
- Same process
### Phase 4: Establish Sync Process (Week 5)
1. **Document sync procedure**
2. **Create GitHub Action for version check**
3. **Add CHANGELOG.md to template**
---
## Project-Specific Customizations
### mifos-mobile (Self-Service)
| Aspect | Value |
|--------|-------|
| User Type | End User (Client) |
| API Prefix | `/self/` |
| Features | 17 (auth, accounts, transfer, etc.) |
| Auth | Username/Password + Passcode |
### mobile-wallet (Mifos Pay)
| Aspect | Value |
|--------|-------|
| User Type | Wallet User |
| API Prefix | `/wallet/` (different API) |
| Features | wallet, send, receive, history, etc. |
| Auth | Phone + OTP |
### android-client (Field Officer)
| Aspect | Value |
|--------|-------|
| User Type | Staff (Field Officer) |
| API Prefix | `/` (full API access) |
| Features | clients, loans, groups, collections, etc. |
| Auth | Username/Password + Staff permissions |
### mifos-x-group-banking
| Aspect | Value |
|--------|-------|
| User Type | Group Leader |
| API Prefix | `/groups/` |
| Features | groups, meetings, attendance, collections |
| Auth | Username/Password + Group permissions |
---
## Template Versioning
```markdown
# CHANGELOG.md (in template)
## [1.1.0] - 2025-02-01
### Added
- Testing documentation templates
- /verify-tests command
### Changed
- Improved gap-analysis comprehensive view
## [1.0.0] - 2025-01-05
### Added
- Initial 5-layer lifecycle framework
- O(1) lookup pattern
- All command templates
```
### Version Compatibility
| Template Version | mifos-mobile | mobile-wallet | android-client |
|------------------|--------------|---------------|----------------|
| 1.0.0 | ✅ | - | - |
| 1.1.0 | ✅ | ✅ | - |
---
## Files to Create in Template
### Priority 1: Framework Documentation
| File | Purpose | Lines |
|------|---------|:-----:|
| `_framework/5-LAYER-LIFECYCLE.md` | Core architecture | ~150 |
| `_framework/O1-LOOKUP-PATTERN.md` | Index strategy | ~100 |
| `_framework/COMMAND-REFERENCE.md` | All commands | ~200 |
| `_framework/TESTING-STRATEGY.md` | TDD approach | ~150 |
### Priority 2: Templates
| File | Purpose |
|------|---------|
| `_templates/design-spec-layer/*.template.md` | Design layer templates |
| `_templates/server-layer/*.template.md` | Server layer templates |
| `_templates/client-layer/*.template.md` | Client layer templates |
| `_templates/feature-layer/*.template.md` | Feature layer templates |
| `_templates/platform-layer/*.template.md` | Platform layer templates |
### Priority 3: Commands
| File | Purpose |
|------|---------|
| `.claude/commands/gap-analysis.md` | Parameterized |
| `.claude/commands/gap-planning.md` | Parameterized |
| `.claude/commands/design.md` | Parameterized |
| `.claude/commands/implement.md` | Parameterized |
| `.claude/commands/verify.md` | Parameterized |
---
## Success Criteria
### Template
- [ ] All framework docs in `_framework/`
- [ ] All templates in `_templates/`
- [ ] Parameterized commands in `.claude/commands/`
- [ ] PROJECT_CONFIG.md template
- [ ] SYNC_GUIDE.md documentation
### Each Derived Project
- [ ] PROJECT.md configured
- [ ] Feature specs in design-spec-layer
- [ ] API docs in server-layer
- [ ] Index files generated
- [ ] Commands working with project config
---
## Open Questions
1. **Command Override Strategy**
- Should projects fully override commands or extend them?
- How to handle project-specific commands?
2. **Sync Frequency**
- How often should projects sync from template?
- Breaking change policy?
3. **Feature Naming**
- Standardize feature names across projects?
- Or allow project-specific naming?
4. **Testing**
- Should test framework be in template?
- Or project-specific?
---
## Next Steps
1. Review this plan
2. Decide on sync strategy (subtree vs submodule vs copy)
3. Start Phase 1: Prepare template
4. Create PR to kmp-project-template
---
## Commands After Migration
```bash
# In any derived project
/gap-analysis # Reads PROJECT.md, shows project-specific status
/gap-planning design # Plans based on project features
/implement auth # Implements based on project specs
# Sync from template
git subtree pull --prefix=claude-product-cycle/_framework \
https://github.com/openMF/kmp-project-template.git main --squash
```

View File

@ -1,354 +0,0 @@
# PRODUCT MAP - Mifos Mobile
> **Purpose**: Central navigation hub for feature development across sessions
> **Last Updated**: 2025-12-30
> **Current Focus**: Design Layer Refinement (2025 Fintech Patterns)
---
## Quick Resume Commands
```bash
# Full 5-layer gap analysis dashboard
/gap-analysis
# Layer-specific analysis
/gap-analysis design # Design layer (SPEC, MOCKUP, API docs)
/gap-analysis server # Server layer (Fineract endpoints)
/gap-analysis client # Client layer (Network, Data)
/gap-analysis feature # Feature layer (ViewModel, Screen)
/gap-analysis platform # Platform layer (Android, iOS, Desktop, Web)
# Feature-specific analysis (all 5 layers)
/gap-analysis [feature-name]
# Plan improvements
/gap-planning [feature-name]
# Continue design work on specific feature
/design [feature-name]
# Implement after design is approved
/implement [feature-name]
# Verify implementation matches spec
/verify [feature-name]
# Check current status
/projectstatus
```
---
## Feature Registry
### Core Features (16 Total)
| # | Feature | Design | Mockup | Client | UI | Status |
|---|---------|--------|--------|--------|-----|--------|
| 1 | **auth** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 2 | **home** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 3 | **accounts** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 4 | **savings-account** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 5 | **loan-account** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 6 | **share-account** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 7 | **beneficiary** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 8 | **transfer** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 9 | **recent-transaction** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 10 | **notification** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 11 | **settings** | ✅ | ✅ v2.0 | - | ✅ | Mockup Redesigned |
| 12 | **passcode** | ✅ | ✅ v2.0 | - | ✅ | Mockup Redesigned |
| 13 | **guarantor** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
| 14 | **qr** | ✅ | ✅ v2.0 | - | ✅ | Mockup Redesigned |
| 15 | **location** | ✅ | ✅ v2.0 | - | ✅ | Mockup Redesigned |
| 16 | **client-charge** | ✅ | ✅ v2.0 | ✅ | ✅ | Mockup Redesigned |
### New Features (Planned)
| # | Feature | Design | Mockup | Client | UI | Status |
|---|---------|--------|--------|--------|-----|--------|
| 17 | **dashboard** | ✅ | ✅ v2.0 | ✅ | ❌ | Mockup Redesigned |
---
## 5-Layer Product Lifecycle
```
┌─────────────────────────────────────────────────────────────┐
│ PRODUCT LIFECYCLE │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. DESIGN LAYER → SPEC + MOCKUP + API documentation │
│ ↓ │
│ 2. SERVER LAYER → Fineract API endpoints (actual) │
│ ↓ │
│ 3. CLIENT LAYER → Network services, Repositories │
│ ↓ │
│ 4. FEATURE LAYER → ViewModels, Screens, Navigation │
│ ↓ │
│ 5. PLATFORM LAYER → Android, iOS, Desktop, Web │
│ │
└─────────────────────────────────────────────────────────────┘
```
## Layer Definitions
### 1. Design Layer (`/design`, `/gap-analysis design`)
**Location**: `claude-product-cycle/design-spec-layer/`
| Component | Location | Purpose |
|-----------|----------|---------|
| SPEC.md | `features/[feature]/SPEC.md` | Requirements, user stories |
| MOCKUP.md | `features/[feature]/MOCKUP.md` | UI/UX designs, v2.0 patterns |
| API.md | `features/[feature]/API.md` | Endpoint definitions |
| STATUS.md | `features/[feature]/STATUS.md` | Implementation status |
| mockup-tools/ | `mockup-tools/` | Figma plugin, templates |
### 2. Server Layer (`/gap-analysis server`)
**Location**: `claude-product-cycle/server-layer/`
| Component | Location | Purpose |
|-----------|----------|---------|
| FINERACT_API.md | `server-layer/FINERACT_API.md` | All available endpoints |
| Base URL | `https://tt.mifos.community/fineract-provider/api/v1/self/` | Demo server |
### 3. Client Layer (`/client`, `/gap-analysis client`)
**Location**: `core/network/` + `core/data/`
| Component | Location |
|-----------|----------|
| API Service | `core/network/services/[Feature]Service.kt` |
| Repository | `core/data/repository/[Feature]Repository.kt` |
| Models | `core/model/[feature]/` |
### 4. Feature Layer (`/feature`, `/gap-analysis feature`)
**Location**: `feature/[feature]/`
| Component | Location |
|-----------|----------|
| ViewModel | `feature/[feature]/src/.../viewmodel/` |
| Screen | `feature/[feature]/src/.../ui/` |
| Navigation | `cmp-navigation/src/.../navigation/` |
| DI Module | `feature/[feature]/src/.../di/` |
### 5. Platform Layer (`/gap-analysis platform`)
**Location**: `cmp-android/`, `cmp-ios/`, `cmp-desktop/`, `cmp-web/`
| Platform | Module | Status |
|----------|--------|--------|
| 🤖 Android | `cmp-android/` | Production Ready |
| 🍎 iOS | `cmp-ios/` | Production Ready |
| 🖥️ Desktop | `cmp-desktop/` | Beta |
| 🌐 Web | `cmp-web/` | Alpha |
---
## Current Work Session
### In Progress: Design Layer Enhancement
**Goal**: Upgrade all mockups to 2025 professional fintech standards
**Reference Sources**:
- [Finix Banking UI Kit](https://dribbble.com/shots/25774459-Finix-Mobile-Banking-UI-Kit)
- [Purrweb Best Practices](https://www.purrweb.com/blog/banking-app-design/)
- [Mobbin Revolut](https://mobbin.com/explore/screens/d66df812-03a0-447f-879b-165318d669c8)
**2025 Patterns to Add**:
| Pattern | Priority | Features Affected |
|---------|----------|-------------------|
| Spending Analytics Chart | High | home, accounts |
| Recent Recipients (P2P) | High | home, transfer |
| Upcoming Bills Section | High | home |
| AI Assistant Entry Point | Medium | home |
| Gamification Elements | Medium | home, savings-account |
| Quick Amount Shortcuts | Medium | transfer |
| Card Freeze Quick Action | Low | home, settings |
### Todo Queue
1. ⏳ **home** - Add 2025 enhancements section (IN PROGRESS)
2. ⬚ **accounts** - Add spending analytics integration
3. ⬚ **transfer** - Add quick amounts, recent recipients
4. ⬚ **dashboard** - Create full MOCKUP.md (NEW FEATURE)
5. ⬚ Remaining 12 features - Review and polish
---
## Feature Dependencies
```
┌─────────────────────────────────────────────────────────────────┐
│ NAVIGATION GRAPH │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ROOT_GRAPH │
│ │ │
│ ├── AUTH_GRAPH │
│ │ └── auth ──────────────────────────┐ │
│ │ │ │
│ ├── PASSCODE_GRAPH │ │
│ │ └── passcode ◄─────────────────────┘ │
│ │ │ │
│ │ ▼ │
│ └── MAIN_GRAPH ◄─────────────────────────────────────── │
│ │ │
│ ├── home (Tab 1) ─────────────────────────────┐ │
│ │ ├── → accounts │ │
│ │ ├── → transfer │ │
│ │ ├── → notification │ │
│ │ └── → qr │ │
│ │ │ │
│ ├── accounts (Tab 2) ──────────────────────────┤ │
│ │ ├── → savings-account │ │
│ │ ├── → loan-account │ │
│ │ └── → share-account │ │
│ │ │ │
│ ├── transfer (FAB) ────────────────────────────┤ │
│ │ └── → beneficiary │ │
│ │ │ │
│ └── profile (Tab 4) ───────────────────────────┘ │
│ ├── → settings │
│ ├── → client-charge │
│ ├── → recent-transaction │
│ ├── → guarantor │
│ └── → location │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## File Paths Quick Reference
### Design Specs
```
claude-product-cycle/design-spec-layer/
├── _shared/
│ └── COMPONENTS.md # Shared design system
├── features/
│ ├── auth/
│ │ ├── SPEC.md
│ │ ├── API.md
│ │ ├── MOCKUP.md
│ │ └── STATUS.md
│ ├── home/
│ │ ├── SPEC.md
│ │ ├── API.md
│ │ ├── MOCKUP.md # 🔄 Enhancing with 2025 patterns
│ │ └── STATUS.md
│ ├── accounts/
│ ├── savings-account/
│ ├── loan-account/
│ ├── share-account/
│ ├── beneficiary/
│ ├── transfer/
│ ├── recent-transaction/
│ ├── notification/
│ ├── settings/
│ ├── passcode/
│ ├── guarantor/
│ ├── qr/
│ ├── location/
│ ├── client-charge/
│ └── dashboard/ # 📋 Needs MOCKUP.md
└── STATUS.md # Master status tracker
```
### Implementation
```
feature/
├── auth/
├── home/
├── account/ # accounts feature
├── savings-account/
├── loan-account/
├── share-account/
├── beneficiary/
├── transfer-process/ # transfer feature
├── recent-transaction/
├── notification/
├── settings/
├── guarantor/
├── qr-code/ # qr feature
├── location/
└── user-profile/ # includes client-charge
core/
├── network/services/ # API services
├── data/repository/ # Repositories
└── model/ # Domain models
```
---
## Resume Instructions
When resuming work after context compaction:
### 1. Read This File First
```
Read: claude-product-cycle/PRODUCT_MAP.md
```
### 2. Check Current Session Status
```
Look at "Current Work Session" section above
```
### 3. Continue From Todo Queue
```
Pick the first ⏳ or ⬚ item and continue
```
### 4. For Design Work
```
Read: claude-product-cycle/design-spec-layer/_shared/COMPONENTS.md
Read: claude-product-cycle/design-spec-layer/features/[feature]/MOCKUP.md
```
### 5. For Implementation Work
```
Read: claude-product-cycle/design-spec-layer/features/[feature]/SPEC.md
Read: claude-product-cycle/design-spec-layer/features/[feature]/API.md
```
---
## Design System Quick Reference
### Color Palette
| Name | Light | Dark | Usage |
|------|-------|------|-------|
| Primary Gradient | #667EEA#764BA2 | Same (85%) | Hero cards, CTAs |
| Secondary Gradient | #11998E#38EF7D | Same | Success, savings |
| Accent Gradient | #FC466B#3F5EFB | Same | Alerts, special |
| Success | #00D09C | #00D09C | Positive amounts |
| Error | #FF4757 | #FF4757 | Negative, urgent |
| Warning | #FFB800 | #FFB800 | Pending states |
### Typography
| Style | Size | Weight | Usage |
|-------|------|--------|-------|
| Display | 36sp | ExtraBold | Balance amounts |
| Headline | 20sp | Bold | Section titles |
| Body | 14sp | Regular | Content text |
| Label | 12sp | Medium | Captions, badges |
### Spacing
| Token | Value |
|-------|-------|
| xs | 4dp |
| sm | 8dp |
| md | 12dp |
| lg | 16dp |
| xl | 20dp |
| xxl | 24dp |
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-30 | Created PRODUCT_MAP.md for session continuity |

View File

@ -1,535 +0,0 @@
# Test Stubs Guide
> Auto-generated test scaffolding for TDD support in `/implement` command
---
## Overview
The `/implement` command automatically generates test stubs (Phase 5) to support Test-Driven Development. This guide explains the generated files, how to use them, and best practices.
---
## Generated Test Files
When running `/implement [feature]`, the following test files are created:
```
feature/[feature]/
├── src/
│ ├── commonTest/kotlin/org/mifos/mobile/feature/[feature]/
│ │ ├── [Feature]ViewModelTest.kt # ViewModel unit tests
│ │ └── fake/
│ │ └── Fake[Feature]Repository.kt # Test double
│ │
│ └── androidInstrumentedTest/kotlin/org/mifos/mobile/feature/[feature]/
│ └── [Feature]ScreenTest.kt # Compose UI tests
```
---
## Test Patterns
### 1. ViewModel Test Pattern
```kotlin
class ${Feature}ViewModelTest {
// Rule for coroutine testing
private val mainDispatcherRule = MainDispatcherRule()
private lateinit var viewModel: ${Feature}ViewModel
private lateinit var fakeRepository: Fake${Feature}Repository
@BeforeTest
fun setup() {
fakeRepository = Fake${Feature}Repository()
viewModel = ${Feature}ViewModel(repository = fakeRepository)
}
// Test Categories:
// 1. Initial State Tests
@Test
fun `initial state is loading`() = runTest {
viewModel.stateFlow.test {
val state = awaitItem()
assertTrue(state.uiState is ${Feature}ScreenState.Loading)
}
}
// 2. Success State Tests
@Test
fun `data loaded successfully shows success state`() = runTest {
fakeRepository.setSuccessResponse(testData)
viewModel.loadData()
viewModel.stateFlow.test {
val state = expectMostRecentItem()
assertTrue(state.uiState is ${Feature}ScreenState.Success)
}
}
// 3. Error State Tests
@Test
fun `data load failure shows error state`() = runTest {
fakeRepository.setErrorResponse("Network error")
viewModel.loadData()
viewModel.stateFlow.test {
val state = expectMostRecentItem()
assertTrue(state.uiState is ${Feature}ScreenState.Error)
}
}
// 4. Action Tests
@Test
fun `action updates state correctly`() = runTest {
viewModel.trySendAction(${Feature}Action.SomeAction)
viewModel.stateFlow.test {
// Verify state change
}
}
// 5. Event Tests
@Test
fun `action triggers navigation event`() = runTest {
viewModel.trySendAction(${Feature}Action.ItemClicked(id))
viewModel.eventFlow.test {
assertEquals(${Feature}Event.NavigateToDetail(id), awaitItem())
}
}
}
```
### 2. Screen Test Pattern
```kotlin
class ${Feature}ScreenTest {
@get:Rule
val composeTestRule = createComposeRule()
// Test Categories:
// 1. Loading State
@Test
fun loadingState_displaysLoadingIndicator() {
val state = ${Feature}State(uiState = ${Feature}ScreenState.Loading)
composeTestRule.setContent {
${Feature}Content(state = state, onAction = {})
}
composeTestRule
.onNodeWithTag(${Feature}TestTags.LOADING)
.assertIsDisplayed()
}
// 2. Success State
@Test
fun successState_displaysContent() {
val state = ${Feature}State(
uiState = ${Feature}ScreenState.Success(testData)
)
composeTestRule.setContent {
${Feature}Content(state = state, onAction = {})
}
composeTestRule
.onNodeWithTag(${Feature}TestTags.SCREEN)
.assertIsDisplayed()
composeTestRule
.onNodeWithTag(${Feature}TestTags.LIST)
.assertIsDisplayed()
}
// 3. Error State
@Test
fun errorState_displaysErrorMessage() {
val state = ${Feature}State(
uiState = ${Feature}ScreenState.Error("Network error")
)
composeTestRule.setContent {
${Feature}Content(state = state, onAction = {})
}
composeTestRule
.onNodeWithTag(${Feature}TestTags.ERROR)
.assertIsDisplayed()
composeTestRule
.onNodeWithText("Network error")
.assertIsDisplayed()
}
// 4. Empty State
@Test
fun emptyState_displaysEmptyMessage() {
val state = ${Feature}State(
uiState = ${Feature}ScreenState.Success(emptyList())
)
composeTestRule.setContent {
${Feature}Content(state = state, onAction = {})
}
composeTestRule
.onNodeWithTag(${Feature}TestTags.EMPTY)
.assertIsDisplayed()
}
// 5. User Interaction
@Test
fun itemClick_triggersAction() {
var actionReceived: ${Feature}Action? = null
val state = ${Feature}State(
uiState = ${Feature}ScreenState.Success(testData)
)
composeTestRule.setContent {
${Feature}Content(
state = state,
onAction = { actionReceived = it }
)
}
composeTestRule
.onNodeWithTag("${feature}:item:1")
.performClick()
assertEquals(${Feature}Action.ItemClicked(1), actionReceived)
}
}
```
### 3. Fake Repository Pattern
```kotlin
class Fake${Feature}Repository : ${Feature}Repository {
// Call tracking
var loadCallCount = 0
private set
// Configurable response
private var response: DataState<List<${Model}>> = DataState.Loading
// Setup methods
fun setSuccessResponse(data: List<${Model}>) {
response = DataState.Success(data)
}
fun setErrorResponse(message: String) {
response = DataState.Error(message)
}
fun setEmptyResponse() {
response = DataState.Success(emptyList())
}
fun setLoadingState() {
response = DataState.Loading
}
// Repository implementation
override fun get${Feature}(): Flow<DataState<List<${Model}>>> = flow {
loadCallCount++
emit(response)
}
// Reset for test isolation
fun reset() {
loadCallCount = 0
response = DataState.Loading
}
}
```
---
## TestTag Convention
### Naming Pattern
```
{feature}:{component}:{identifier}
```
### Standard Tags
| Component | Pattern | Example |
|-----------|---------|---------|
| Screen container | `{feature}:screen` | `beneficiary:screen` |
| Loading indicator | `{feature}:loading` | `beneficiary:loading` |
| Error container | `{feature}:error` | `beneficiary:error` |
| Empty state | `{feature}:empty` | `beneficiary:empty` |
| List container | `{feature}:list` | `beneficiary:list` |
| List item | `{feature}:item:{id}` | `beneficiary:item:123` |
| Action button | `{feature}:{action}` | `beneficiary:add` |
| Retry button | `{feature}:retry` | `beneficiary:retry` |
| Input field | `{feature}:input:{name}` | `auth:input:username` |
| Form submit | `{feature}:submit` | `auth:submit` |
### TestTags Object
Each feature should have a TestTags object:
```kotlin
object ${Feature}TestTags {
const val SCREEN = "${feature}:screen"
const val LOADING = "${feature}:loading"
const val ERROR = "${feature}:error"
const val EMPTY = "${feature}:empty"
const val LIST = "${feature}:list"
const val RETRY = "${feature}:retry"
fun item(id: Long) = "${feature}:item:$id"
}
```
### Applying TestTags
```kotlin
@Composable
fun ${Feature}Screen(...) {
Scaffold(
modifier = Modifier.testTag(${Feature}TestTags.SCREEN)
) {
when (state.uiState) {
is Loading -> LoadingIndicator(
modifier = Modifier.testTag(${Feature}TestTags.LOADING)
)
is Error -> ErrorView(
modifier = Modifier.testTag(${Feature}TestTags.ERROR)
)
is Success -> ContentList(
modifier = Modifier.testTag(${Feature}TestTags.LIST)
)
}
}
}
```
---
## Test Dependencies
### build.gradle.kts
```kotlin
kotlin {
sourceSets {
commonTest.dependencies {
implementation(kotlin("test"))
implementation(libs.kotlinx.coroutines.test)
implementation(libs.turbine)
}
androidInstrumentedTest.dependencies {
implementation(libs.compose.ui.test.junit4)
implementation(libs.compose.ui.test.manifest)
}
}
}
```
### Key Libraries
| Library | Purpose | Usage |
|---------|---------|-------|
| `kotlin-test` | Assertions | `assertEquals`, `assertTrue` |
| `kotlinx-coroutines-test` | Coroutine testing | `runTest`, `TestDispatcher` |
| `turbine` | Flow testing | `stateFlow.test { }` |
| `compose-ui-test` | Compose UI testing | `onNodeWithTag`, `performClick` |
---
## Test Execution
### Run Commands
```bash
# Run all tests for a feature
./gradlew :feature:${feature}:test
# Run ViewModel tests only (commonTest)
./gradlew :feature:${feature}:jvmTest
# Run Screen tests (Android instrumented)
./gradlew :feature:${feature}:connectedAndroidTest
# Run with coverage
./gradlew :feature:${feature}:test jacocoTestReport
```
### CI Integration
```yaml
# .github/workflows/test.yml
- name: Run Unit Tests
run: ./gradlew testDebug
- name: Run UI Tests
run: ./gradlew connectedAndroidTest
```
---
## TDD Workflow
### Red-Green-Refactor
```
1. WRITE FAILING TEST (Red)
└─ Generated stub has TODO assertions
└─ Test fails because implementation is incomplete
2. IMPLEMENT (Green)
└─ Write minimum code to pass
└─ Fill in ViewModel/Screen logic
3. REFACTOR (Clean)
└─ Improve code quality
└─ Keep tests passing
4. VERIFY
└─ Run /verify [feature]
└─ Check TestTag validation
```
### Stub Completion Checklist
After `/implement` generates stubs:
- [ ] Fill in test data fixtures
- [ ] Complete assertion logic (replace TODOs)
- [ ] Add edge case tests
- [ ] Verify all TestTags are applied
- [ ] Run tests to confirm passing
- [ ] Update TESTING_STATUS.md
---
## Common Test Scenarios
### 1. Pagination Test
```kotlin
@Test
fun `load more appends to list`() = runTest {
fakeRepository.setSuccessResponse(page1Data)
viewModel.loadData()
fakeRepository.setSuccessResponse(page2Data)
viewModel.trySendAction(${Feature}Action.LoadMore)
viewModel.stateFlow.test {
val state = expectMostRecentItem()
val data = (state.uiState as Success).data
assertEquals(page1Data + page2Data, data)
}
}
```
### 2. Pull-to-Refresh Test
```kotlin
@Test
fun `refresh replaces data`() = runTest {
fakeRepository.setSuccessResponse(oldData)
viewModel.loadData()
fakeRepository.setSuccessResponse(newData)
viewModel.trySendAction(${Feature}Action.Refresh)
viewModel.stateFlow.test {
val state = expectMostRecentItem()
val data = (state.uiState as Success).data
assertEquals(newData, data)
}
}
```
### 3. Form Validation Test
```kotlin
@Test
fun `invalid input shows validation error`() = runTest {
viewModel.trySendAction(${Feature}Action.Submit(invalidInput))
viewModel.stateFlow.test {
val state = expectMostRecentItem()
assertNotNull(state.validationError)
}
}
```
### 4. Dialog Confirmation Test
```kotlin
@Test
fun `delete shows confirmation dialog`() = runTest {
viewModel.trySendAction(${Feature}Action.DeleteClicked(id))
viewModel.stateFlow.test {
val state = expectMostRecentItem()
assertTrue(state.dialogState is DialogState.Confirmation)
}
}
@Test
fun `confirm delete triggers delete action`() = runTest {
viewModel.trySendAction(${Feature}Action.ConfirmDelete(id))
assertEquals(1, fakeRepository.deleteCallCount)
}
```
---
## Troubleshooting
### Common Issues
| Issue | Cause | Solution |
|-------|-------|----------|
| Test timeout | Missing `runTest` | Wrap in `runTest { }` |
| Flow not emitting | Wrong dispatcher | Use `MainDispatcherRule` |
| Node not found | Missing testTag | Add `Modifier.testTag()` |
| Assertion failure | Stale state | Use `expectMostRecentItem()` |
### Debug Tips
```kotlin
// Print state for debugging
viewModel.stateFlow.test {
val state = expectMostRecentItem()
println("Current state: $state")
// assertions...
}
// Print compose tree
composeTestRule.onRoot().printToLog("COMPOSE_TREE")
```
---
## Related Files
- [TESTING_STATUS.md](./feature-layer/TESTING_STATUS.md) - Feature test coverage
- [/verify command](../.claude/commands/verify.md) - TestTag validation
- [/implement command](../.claude/commands/implement.md) - Test stub generation
---
## Commands
```bash
# Generate test stubs for feature
/implement [feature] # Phase 5 generates tests
# Verify TestTag compliance
/verify [feature] # Includes TestTag validation
# Check testing gaps
/gap-analysis testing # Shows test coverage gaps
```

View File

@ -1,169 +0,0 @@
# Feature → Client Components Map
> **13 services** | **17 repositories** | **2 DI modules**
---
## Feature to Components (O(1) Lookup)
| Feature | Services | Repositories | Notes |
|---------|----------|--------------|-------|
| auth | AuthenticationService, RegistrationService, UserDetailsService | UserAuthRepository, UserDataRepository | Login, Register, Password |
| home | ClientService, NotificationService | HomeRepository, NotificationRepository | Dashboard, Profile |
| accounts | ClientService | AccountsRepository | Account listing |
| loan-account | LoanAccountsListService, GuarantorService | LoanRepository, GuarantorRepository, ReviewLoanApplicationRepository | Loan details |
| savings-account | SavingAccountsListService | SavingsAccountRepository | Savings details |
| share-account | ShareAccountService | ShareAccountRepository | Share details |
| beneficiary | BeneficiaryService | BeneficiaryRepository | TPT beneficiaries |
| transfer | ThirdPartyTransferService, SavingAccountsListService | TransferRepository, ThirdPartyTransferRepository | Fund transfer |
| notification | NotificationService | NotificationRepository | Push notifications |
| recent-transaction | RecentTransactionsService | RecentTransactionRepository | Transaction history |
| client-charge | ClientChargeService | ClientChargeRepository | Client charges |
| settings | UserDetailsService | UserDetailRepository | Password change |
| guarantor | GuarantorService | GuarantorRepository | Loan guarantors |
| user-profile | ClientService | ClientRepository, UserDetailRepository | Profile display |
---
## Services Inventory (13)
| Service | File | Key Methods |
|---------|------|-------------|
| AuthenticationService | AuthenticationService.kt | `authenticate()` |
| RegistrationService | RegistrationService.kt | `registerUser()`, `verifyUser()` |
| ClientService | ClientService.kt | `clients()`, `getClientForId()`, `getClientAccounts()`, `getClientImage()` |
| LoanAccountsListService | LoanAccountsListService.kt | `getLoanWithAssociations()`, `createLoansAccount()`, `withdrawLoanAccount()` |
| SavingAccountsListService | SavingAccountsListService.kt | `getSavingsWithAssociations()`, `makeTransfer()`, `submitSavingAccountApplication()` |
| BeneficiaryService | BeneficiaryService.kt | `beneficiaryList()`, `createBeneficiary()`, `updateBeneficiary()`, `deleteBeneficiary()` |
| ThirdPartyTransferService | ThirdPartyTransferService.kt | `accountTransferTemplate()`, `makeTransfer()` |
| NotificationService | NotificationService.kt | `getUserNotificationId()`, `registerNotification()`, `updateRegisterNotification()` |
| RecentTransactionsService | RecentTransactionsService.kt | `getRecentTransactionsList()` |
| UserDetailsService | UserDetailsService.kt | `updateAccountPassword()` |
| ShareAccountService | ShareAccountService.kt | `getShareProducts()`, `submitShareApplication()`, `getShareAccountDetails()` |
| GuarantorService | GuarantorService.kt | `getGuarantorList()`, `getGuarantorTemplate()`, `createGuarantor()` |
| ClientChargeService | ClientChargeService.kt | `getClientChargeList()`, `getChargeList()` |
---
## Repositories Inventory (17)
| Repository | Implementation | Depends On |
|------------|----------------|------------|
| AccountsRepository | AccountsRepositoryImp | ClientService |
| BeneficiaryRepository | BeneficiaryRepositoryImp | BeneficiaryService |
| ClientChargeRepository | ClientChargeRepositoryImp | ClientChargeService |
| ClientRepository | ClientRepositoryImp | ClientService |
| GuarantorRepository | GuarantorRepositoryImp | GuarantorService |
| HomeRepository | HomeRepositoryImp | ClientService |
| LoanRepository | LoanRepositoryImp | LoanAccountsListService |
| NotificationRepository | NotificationRepositoryImp | NotificationService |
| RecentTransactionRepository | RecentTransactionRepositoryImp | RecentTransactionsService |
| ReviewLoanApplicationRepository | ReviewLoanApplicationRepositoryImpl | LoanAccountsListService |
| SavingsAccountRepository | SavingsAccountRepositoryImp | SavingAccountsListService |
| ShareAccountRepository | ShareAccountRepositoryImp | ShareAccountService |
| ThirdPartyTransferRepository | ThirdPartyTransferRepositoryImp | ThirdPartyTransferService |
| TransferRepository | TransferRepositoryImp | SavingAccountsListService |
| UserAuthRepository | UserAuthRepositoryImp | AuthenticationService |
| UserDataRepository | AuthenticationUserRepository | DataStore |
| UserDetailRepository | UserDetailRepositoryImp | UserDetailsService |
---
## DI Modules
| Module | Location | Provides |
|--------|----------|----------|
| NetworkModule | `core/network/di/NetworkModule.kt` | HttpClient, KtorfitClient, DataManager |
| RepositoryModule | `core/data/di/RepositoryModule.kt` | All 17 repositories as singletons |
---
## Reverse Lookup: Service → Features
| Service | Used By Features |
|---------|------------------|
| AuthenticationService | auth |
| RegistrationService | auth |
| ClientService | home, accounts, user-profile |
| LoanAccountsListService | loan-account |
| SavingAccountsListService | savings-account, transfer |
| BeneficiaryService | beneficiary |
| ThirdPartyTransferService | transfer |
| NotificationService | home, notification |
| RecentTransactionsService | recent-transaction |
| UserDetailsService | auth, settings |
| ShareAccountService | share-account |
| GuarantorService | loan-account, guarantor |
| ClientChargeService | client-charge |
---
## Reverse Lookup: Repository → Features
| Repository | Used By Features |
|------------|------------------|
| AccountsRepository | accounts |
| BeneficiaryRepository | beneficiary |
| ClientChargeRepository | client-charge |
| ClientRepository | user-profile |
| GuarantorRepository | loan-account, guarantor |
| HomeRepository | home |
| LoanRepository | loan-account |
| NotificationRepository | home, notification |
| RecentTransactionRepository | recent-transaction |
| ReviewLoanApplicationRepository | loan-account |
| SavingsAccountRepository | savings-account |
| ShareAccountRepository | share-account |
| ThirdPartyTransferRepository | transfer |
| TransferRepository | transfer |
| UserAuthRepository | auth |
| UserDataRepository | auth |
| UserDetailRepository | settings, user-profile |
---
## O(1) File Access
| Need | Path |
|------|------|
| Service | `core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/[Name]Service.kt` |
| Repository Interface | `core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repository/[Name]Repository.kt` |
| Repository Impl | `core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repository/[Name]RepositoryImp.kt` |
| Network DI | `core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/di/NetworkModule.kt` |
| Data DI | `core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/di/RepositoryModule.kt` |
---
## Architecture Flow
```
Feature (ViewModel)
Repository (Interface)
RepositoryImpl (Implementation)
DataManager (Service Accessor)
Service (Ktorfit API)
HttpClient (Ktor)
```
---
## Related Files
- [LAYER_STATUS.md](LAYER_STATUS.md) - Implementation status
- [LAYER_GUIDE.md](LAYER_GUIDE.md) - Architecture patterns
- [server-layer/API_INDEX.md](../server-layer/API_INDEX.md) - API endpoints
---
## Auto-Update Rules
| Scenario | Action |
|----------|--------|
| New service added | Add to Services Inventory |
| New repository added | Add to Repositories Inventory + Reverse Lookup |
| Feature uses new service | Update Feature to Components table |

View File

@ -1,174 +0,0 @@
# Client Layer Guide
> **Location**: `core/` (Network + Data)
> **Command**: `/client [Feature]`
---
## Overview
The client layer contains two sub-layers that handle all client-side logic:
```
┌─────────────────────────────────────────────────────────────────────┐
│ CLIENT LAYER (core/) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ core/network/ → API Services (Ktorfit), DTOs, DataManager │
│ │ │
│ ▼ │
│ core/data/ → Repositories, Data transformations │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## Directory Structure
```
core/
├── network/ # API Layer
│ └── src/commonMain/kotlin/.../network/
│ ├── services/
│ │ ├── AuthenticationService.kt
│ │ ├── BeneficiaryService.kt
│ │ ├── ClientService.kt
│ │ ├── LoanAccountsListService.kt
│ │ ├── SavingAccountsListService.kt
│ │ └── ...
│ ├── model/
│ │ └── [Domain]Entity.kt # DTOs
│ ├── DataManager.kt # Service accessor
│ ├── KtorfitClient.kt # Ktorfit setup
│ └── di/
│ └── NetworkModule.kt # Koin registration
├── data/ # Data Layer
│ └── src/commonMain/kotlin/.../data/
│ ├── repository/
│ │ └── [Feature]Repository.kt # Interface
│ ├── repositoryImpl/
│ │ └── [Feature]RepositoryImp.kt # Implementation
│ └── di/
│ └── RepositoryModule.kt # Koin registration
├── model/ # Domain Models (shared)
├── database/ # Local database (Room)
├── datastore/ # Preferences (UserPreferencesRepository)
├── designsystem/ # Design tokens, theme
├── ui/ # Shared UI components
└── common/ # Utilities, dispatchers
```
---
## Implementation Flow
```
/client [Feature]
├── 1. Network Layer
│ ├── Create [Feature]Service.kt (Ktorfit interface)
│ ├── Add to KtorfitClient.kt
│ ├── Add to DataManager.kt
│ └── DTOs in model/ package
└── 2. Data Layer
├── Create [Feature]Repository interface
├── Create [Feature]RepositoryImp implementation
└── Register in RepositoryModule.kt
```
---
## Code Patterns
### Service (Ktorfit Interface)
```kotlin
// core/network/services/[Feature]Service.kt
interface [Feature]Service {
@GET("self/[endpoint]")
suspend fun getData(): [Feature]Entity
@POST("self/[endpoint]")
suspend fun createData(@Body payload: [Request]Entity): ResponseBody
}
```
### DataManager
```kotlin
// core/network/DataManager.kt
class DataManager(
private val ktorfitClient: KtorfitClient,
) {
val [feature]Api by lazy { ktorfitClient.[feature]Api }
}
```
### Repository Interface
```kotlin
// core/data/repository/[Feature]Repository.kt
interface [Feature]Repository {
suspend fun getData(): [DomainModel]
suspend fun createData(param: Param): Result
}
```
### Repository Implementation
```kotlin
// core/data/repositoryImpl/[Feature]RepositoryImp.kt
class [Feature]RepositoryImp(
private val dataManager: DataManager,
@Named(MifosDispatchers.IO.name) private val ioDispatcher: CoroutineDispatcher,
) : [Feature]Repository {
override suspend fun getData(): [DomainModel] = withContext(ioDispatcher) {
dataManager.[feature]Api.getData().toDomainModel()
}
}
```
### Koin Registration
```kotlin
// core/data/di/RepositoryModule.kt
val RepositoryModule = module {
single<[Feature]Repository> {
[Feature]RepositoryImp(get(), get(ioDispatcher))
}
}
```
---
## Critical Rules
```
⚠️ Repository ALWAYS uses DataManager, never raw Ktorfit services!
✅ CORRECT: Repository → DataManager → Service
❌ WRONG: Repository → Service directly
```
---
## Build Commands
```bash
./gradlew :core:network:build
./gradlew :core:data:build
./gradlew :core:model:build
```
---
## Related Files
- Patterns: `claude-product-cycle/design-spec-layer/_shared/PATTERNS.md`
- API Specs: `claude-product-cycle/design-spec-layer/features/[feature]/API.md`

View File

@ -1,171 +0,0 @@
# Client Layer - Status & Memory
> **Layer**: Network + Data
> **Command**: `/client [Feature]`
> **Location**: `core/` (network, data)
---
## Current Status
| Sub-Layer | Components | Status |
|-----------|------------|--------|
| Network (Services) | 13 | Complete |
| Network (DTOs) | 40+ | Complete |
| Data (Repositories) | 17 | Complete |
---
## Layer Structure
```
core/
├── network/ # API Layer
│ └── src/commonMain/kotlin/.../network/
│ ├── DataManager.kt # Service accessor
│ ├── KtorfitClient.kt # Ktorfit setup
│ ├── services/ # API interfaces
│ │ ├── AuthenticationService.kt
│ │ ├── BeneficiaryService.kt
│ │ ├── ClientChargeService.kt
│ │ ├── ClientService.kt
│ │ ├── GuarantorService.kt
│ │ ├── LoanAccountsListService.kt
│ │ ├── NotificationService.kt
│ │ ├── RecentTransactionsService.kt
│ │ ├── RegistrationService.kt
│ │ ├── SavingAccountsListService.kt
│ │ ├── ShareAccountService.kt
│ │ ├── ThirdPartyTransferService.kt
│ │ └── UserDetailsService.kt
│ ├── model/ # DTOs
│ └── di/NetworkModule.kt
├── data/ # Data Layer
│ └── src/commonMain/kotlin/.../data/
│ ├── repository/ # Interfaces
│ ├── repositoryImpl/ # Implementations
│ └── di/RepositoryModule.kt
├── model/ # Domain Models (shared)
├── database/ # Local DB (Room)
├── datastore/ # Preferences
├── designsystem/ # UI components
├── ui/ # Shared UI
└── common/ # Utilities
```
---
## Services (Network Layer)
| Service | Purpose | Base Endpoint |
|---------|---------|---------------|
| AuthenticationService | Login, logout | /self/authentication |
| RegistrationService | User registration | /self/registration |
| ClientService | Client profile | /self/clients |
| UserDetailsService | User details | /self/userdetails |
| SavingAccountsListService | Savings accounts | /self/savingsaccounts |
| LoanAccountsListService | Loan accounts | /self/loanaccounts |
| ShareAccountService | Share accounts | /self/shareaccounts |
| BeneficiaryService | Beneficiaries CRUD | /self/beneficiaries |
| ThirdPartyTransferService | Transfers | /self/accounttransfers |
| RecentTransactionsService | Transaction history | /self/transactions |
| NotificationService | Notifications | /self/notifications |
| GuarantorService | Guarantor management | /self/loans/{id}/guarantors |
| ClientChargeService | Client charges | /self/clients/{id}/charges |
---
## Repositories (Data Layer)
| Repository | Service Used | Status |
|------------|--------------|--------|
| UserAuthRepository | AuthenticationService | Complete |
| UserDataRepository | - (DataStore) | Complete |
| UserDetailRepository | UserDetailsService | Complete |
| ClientRepository | ClientService | Complete |
| AccountsRepository | Multiple services | Complete |
| SavingsAccountRepository | SavingAccountsListService | Complete |
| LoanRepository | LoanAccountsListService | Complete |
| ShareAccountRepository | ShareAccountService | Complete |
| BeneficiaryRepository | BeneficiaryService | Complete |
| TransferRepository | Multiple services | Complete |
| ThirdPartyTransferRepository | ThirdPartyTransferService | Complete |
| RecentTransactionRepository | RecentTransactionsService | Complete |
| NotificationRepository | NotificationService | Complete |
| GuarantorRepository | GuarantorService | Complete |
| ClientChargeRepository | ClientChargeService | Complete |
| HomeRepository | Multiple services | Complete |
| ReviewLoanApplicationRepository | LoanAccountsListService | Complete |
---
## DataManager APIs
| API | Service | Lazy Loaded |
|-----|---------|-------------|
| authenticationApi | AuthenticationService | Yes |
| registrationApi | RegistrationService | Yes |
| clientsApi | ClientService | Yes |
| userDetailsApi | UserDetailsService | Yes |
| savingAccountsListApi | SavingAccountsListService | Yes |
| loanAccountsListApi | LoanAccountsListService | Yes |
| shareAccountApi | ShareAccountService | Yes |
| beneficiaryApi | BeneficiaryService | Yes |
| thirdPartyTransferApi | ThirdPartyTransferService | Yes |
| recentTransactionsApi | RecentTransactionsService | Yes |
| notificationApi | NotificationService | Yes |
| guarantorApi | GuarantorService | Yes |
| clientChargeApi | ClientChargeService | Yes |
---
## Critical Rules
```
REPOSITORY ALWAYS USES DataManager!
CORRECT: Repository → DataManager → Service
WRONG: Repository → Service directly
```
---
## Build Commands
```bash
./gradlew :core:network:build
./gradlew :core:data:build
./gradlew :core:model:build
```
---
## DI Modules
| Module | Location | Registration |
|--------|----------|--------------|
| NetworkModule | core/network/di/ | DataManager, KtorfitClient |
| RepositoryModule | core/data/di/ | All Repositories |
| PreferenceModule | core/datastore/di/ | UserPreferencesRepository |
| DatabaseModule | core/database/di/ | Room Database |
All registered in: `cmp-navigation/di/KoinModules.kt`
---
## Related Docs
- Patterns: `claude-product-cycle/design-spec-layer/_shared/PATTERNS.md`
- API Specs: `claude-product-cycle/design-spec-layer/features/[feature]/API.md`
- Layer Guide: `claude-product-cycle/client-layer/LAYER_GUIDE.md`
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-26 | Created LAYER_STATUS.md |
| 2025-12-26 | All 17 repositories verified complete |

View File

@ -1,192 +0,0 @@
# Client Layer - Testing Status
> Repository and service testing documentation
---
## Overview
The client layer handles data operations. Testing ensures repositories correctly transform API responses and handle errors.
---
## Current State
| Component | Total | Tested | Coverage |
|-----------|:-----:|:------:|:--------:|
| Services | 13 | 0 | 0% |
| Repositories | 17 | 14 | 82% |
| DataStore | 3 | 3 | 100% |
---
## Testing Scope
| Component | Test Type | Purpose |
|-----------|-----------|---------|
| Services | Unit Tests | Verify API call construction |
| Repositories | Unit Tests | Verify data transformation |
| DataStore | Unit Tests | Verify local persistence |
---
## Repository Testing Status
### Existing Tests (14)
| # | Repository | Tests | File |
|:-:|------------|:-----:|------|
| 1 | AccountsRepository | 2 | `AccountsRepositoryTest.kt` |
| 2 | BeneficiaryRepository | 1 | `BeneficiaryRepositoryTest.kt` |
| 3 | ClientChargeRepository | 1 | `ClientChargeRepositoryTest.kt` |
| 4 | ClientRepository | 1 | `ClientRepositoryTest.kt` |
| 5 | GuarantorRepository | 1 | `GuarantorRepositoryTest.kt` |
| 6 | HomeRepository | 1 | `HomeRepositoryTest.kt` |
| 7 | LoanRepository | 1 | `LoanRepositoryTest.kt` |
| 8 | NotificationRepository | 1 | `NotificationRepositoryTest.kt` |
| 9 | RecentTransactionRepository | 1 | `RecentTransactionRepositoryTest.kt` |
| 10 | SavingsAccountRepository | 1 | `SavingsAccountRepositoryTest.kt` |
| 11 | ShareAccountRepository | 1 | `ShareAccountRepositoryTest.kt` |
| 12 | ThirdPartyTransferRepository | 1 | `ThirdPartyTransferRepositoryTest.kt` |
| 13 | TransferRepository | 1 | `TransferRepositoryTest.kt` |
| 14 | UserAuthRepository | - | (needs tests) |
**Location**: `core/data/src/commonTest/kotlin/org/mifos/mobile/core/data/repository/`
---
## Repository Test Coverage Matrix
| # | Repository | Success | Error | Empty | Offline | Status |
|:-:|------------|:-------:|:-----:|:-----:|:-------:|:------:|
| 1 | AccountsRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 2 | BeneficiaryRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 3 | ClientChargeRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 4 | ClientRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 5 | GuarantorRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 6 | HomeRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 7 | LoanRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 8 | NotificationRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 9 | RecentTransactionRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 10 | SavingsAccountRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 11 | ShareAccountRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 12 | ThirdPartyTransferRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 13 | TransferRepository | ✅ | ⬜ | ⬜ | ⬜ | Partial |
| 14 | UserAuthRepository | ⬜ | ⬜ | ⬜ | ⬜ | Not Started |
| 15 | UserDataRepository | ⬜ | ⬜ | ⬜ | ⬜ | Not Started |
| 16 | UserPreferencesRepository | ⬜ | ⬜ | ⬜ | ⬜ | Not Started |
| 17 | RegistrationRepository | ⬜ | ⬜ | ⬜ | ⬜ | Not Started |
**Legend**: ✅ Tested | ⬜ Not Tested
---
## Missing Tests
### Priority 1 - Auth Flow
- [ ] UserAuthRepository (login, logout, token refresh)
- [ ] UserPreferencesRepository (user settings)
- [ ] RegistrationRepository (sign up flow)
### Priority 2 - Error Handling
- [ ] All repositories: error scenarios
- [ ] All repositories: empty response handling
- [ ] All repositories: offline caching
### Priority 3 - Edge Cases
- [ ] Pagination handling
- [ ] Concurrent request handling
- [ ] Cache invalidation
---
## Fake Repository Implementations
For ViewModel testing, create fake repositories:
**Location**: `core/testing/src/commonMain/kotlin/org/mifos/mobile/core/testing/fake/`
```kotlin
class FakeHomeRepository : HomeRepository {
private var result: DataState<HomeData> = DataState.Loading
fun setResult(result: DataState<HomeData>) {
this.result = result
}
override suspend fun getHomeData(): Flow<DataState<HomeData>> = flow {
emit(result)
}
}
```
### Fake Repositories Needed
| # | Fake Repository | For Testing |
|:-:|-----------------|-------------|
| 1 | FakeHomeRepository | HomeViewModel |
| 2 | FakeUserAuthRepository | LoginViewModel |
| 3 | FakeAccountsRepository | AccountsViewModel |
| 4 | FakeBeneficiaryRepository | BeneficiaryViewModel |
| 5 | FakeLoanRepository | LoanViewModel |
| 6 | FakeSavingsAccountRepository | SavingsViewModel |
| 7 | FakeTransferRepository | TransferViewModel |
| 8 | FakeNotificationRepository | NotificationViewModel |
| 9 | FakeSettingsRepository | SettingsViewModel |
---
## Test Fixtures
**Location**: `core/testing/src/commonMain/kotlin/org/mifos/mobile/core/testing/fixture/`
```kotlin
object ClientAccountsFixture {
fun create(
savingsAccounts: List<SavingAccount> = emptyList(),
loanAccounts: List<LoanAccount> = emptyList(),
shareAccounts: List<ShareAccount> = emptyList()
) = ClientAccounts(
savingsAccounts = savingsAccounts,
loanAccounts = loanAccounts,
shareAccounts = shareAccounts
)
fun withSavings() = create(
savingsAccounts = listOf(SavingAccountFixture.create())
)
}
```
---
## Implementation Priority
| Phase | Scope | Tests |
|:-----:|-------|:-----:|
| 1 | Auth repositories | 15 |
| 2 | Error handling (all repos) | 34 |
| 3 | Fake implementations | 9 |
| 4 | Test fixtures | 12 |
---
## Commands
```bash
# Run client layer tests
./gradlew :core:data:test
# Check test coverage
/gap-analysis client testing
# Plan missing tests
/gap-planning client testing
```
---
## Related Files
- [FEATURE_MAP.md](./FEATURE_MAP.md) - Feature to service mapping
- [LAYER_STATUS.md](./LAYER_STATUS.md) - Implementation status

View File

@ -1,56 +0,0 @@
# Commands Layer
This directory contains slash command definitions for Claude Code integration with the Mifos Mobile project.
## Available Commands
| Command | File | Description |
|---------|------|-------------|
| `/projectstatus` | projectstatus.md | Display project overview and feature status |
| `/design [Feature]` | design.md | Create or update feature specification |
| `/mockup [Feature]` | mockup.md | Generate design mockups (Figma plugin / AI prompts) |
| `/implement [Feature]` | implement.md | Full E2E feature implementation |
| `/client [Feature]` | client.md | Implement Network + Data layers |
| `/feature [Feature]` | feature.md | Implement UI layer (ViewModel + Screen) |
| `/verify [Feature]` | verify.md | Validate implementation vs specification |
## Usage
Copy these files to your `.claude/commands/` directory or reference them directly when working with Claude Code.
## Workflow
```
/projectstatus → See current state
/design [Feature] → Create specification (Opus)
/mockup [Feature] → Generate design mockups
│ (Figma plugin or AI prompts)
/implement [Feature] → Full implementation (Sonnet)
/verify [Feature] → Validate implementation
```
## Mockup Pipeline
```
/design [Feature]
├─→ /mockup [Feature] → Figma plugin code
│ OR
├─→ /mockup [Feature] prompts → AI tool prompts
[Generate in Figma / AI Tool]
[Connect Figma MCP]
/implement [Feature] → Code from design
```

View File

@ -1,156 +0,0 @@
# /client - Client Layer Implementation
## Purpose
Implement the client layer (Network + Data) for a feature. This includes DTOs, Services, and Repositories.
---
## Workflow
```
┌───────────────────────────────────────────────────────────────────┐
│ /client [Feature] WORKFLOW │
├───────────────────────────────────────────────────────────────────┤
│ │
│ STEP 1: READ SPEC │
│ ├─→ Read features/[feature]/SPEC.md │
│ ├─→ Read features/[feature]/API.md │
│ └─→ Read server-layer/FINERACT_API.md │
│ │
│ STEP 2: CHECK EXISTING CODE │
│ ├─→ Check core/network/services/ for existing service │
│ ├─→ Check core/data/repository/ for existing repository │
│ └─→ Identify what needs to be created/updated │
│ │
│ STEP 3: NETWORK LAYER │
│ ├─→ Create/update DTOs in core/network/model/ (if needed) │
│ ├─→ Create/update Service interface in core/network/services/ │
│ └─→ Register in NetworkModule │
│ │
│ STEP 4: DATA LAYER │
│ ├─→ Create/update Repository interface │
│ ├─→ Create/update RepositoryImpl │
│ └─→ Register in DataModule │
│ │
│ STEP 5: BUILD & VERIFY │
│ ├─→ ./gradlew :core:network:build │
│ ├─→ ./gradlew :core:data:build │
│ └─→ ./gradlew spotlessApply │
│ │
└───────────────────────────────────────────────────────────────────┘
```
---
## File Locations
| Component | Location |
|-----------|----------|
| DTOs | `core/network/model/` |
| Service Interface | `core/network/services/` |
| Repository Interface | `core/data/repository/` |
| Repository Impl | `core/data/repositoryImpl/` |
| Network DI | `core/network/di/NetworkModule.kt` |
| Data DI | `core/data/di/DataModule.kt` |
---
## Service Pattern
```kotlin
// core/network/services/[Feature]Service.kt
interface [Feature]Service {
@GET(ApiEndPoints.[ENDPOINT])
fun getData(): Flow<DataType>
@GET(ApiEndPoints.[ENDPOINT] + "/{id}")
fun getById(@Path("id") id: Long): Flow<DataType>
@POST(ApiEndPoints.[ENDPOINT])
suspend fun create(@Body payload: PayloadType): HttpResponse
@PUT(ApiEndPoints.[ENDPOINT] + "/{id}")
suspend fun update(
@Path("id") id: Long,
@Body payload: PayloadType,
): HttpResponse
@DELETE(ApiEndPoints.[ENDPOINT] + "/{id}")
suspend fun delete(@Path("id") id: Long): HttpResponse
}
```
---
## Repository Pattern
```kotlin
// core/data/repository/[Feature]Repository.kt
interface [Feature]Repository {
fun getData(): Flow<DataState<List<Data>>>
fun getById(id: Long): Flow<DataState<Data>>
suspend fun create(data: Data): DataState<Unit>
suspend fun update(id: Long, data: Data): DataState<Unit>
suspend fun delete(id: Long): DataState<Unit>
}
// core/data/repositoryImpl/[Feature]RepositoryImpl.kt
class [Feature]RepositoryImpl(
private val service: [Feature]Service,
) : [Feature]Repository {
override fun getData(): Flow<DataState<List<Data>>> = flow {
emit(DataState.Loading)
try {
val result = service.getData().first()
emit(DataState.Success(result))
} catch (e: Exception) {
emit(DataState.Error(e.message ?: "Unknown error"))
}
}
}
```
---
## DI Registration
```kotlin
// core/network/di/NetworkModule.kt
val networkModule = module {
single<[Feature]Service> { get<Ktorfit>().create<[Feature]Service>() }
}
// core/data/di/DataModule.kt
val dataModule = module {
single<[Feature]Repository> { [Feature]RepositoryImpl(get()) }
}
```
---
## Output Template
```
┌──────────────────────────────────────────────────────────────────────┐
│ ✅ CLIENT LAYER COMPLETE │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ Created/Updated: │
│ ├─ core/network/services/[Feature]Service.kt │
│ ├─ core/data/repository/[Feature]Repository.kt │
│ └─ core/data/repositoryImpl/[Feature]RepositoryImpl.kt │
│ │
│ Registered in DI: │
│ ├─ NetworkModule: [Feature]Service ✅ │
│ └─ DataModule: [Feature]Repository ✅ │
│ │
│ 🔨 BUILD: :core:network ✅ :core:data ✅ │
│ 🧹 LINT: spotlessApply ✅ │
│ │
├──────────────────────────────────────────────────────────────────────┤
│ NEXT STEP: │
│ Run: /feature [Feature] │
└──────────────────────────────────────────────────────────────────────┘
```

View File

@ -1,293 +0,0 @@
# /design - Feature Specification
## Purpose
Create or update feature specifications (SPEC.md + API.md) that define what to build and how to build it.
---
## Command Variants
```
/design → Show feature list
/design [Feature] → Full spec review/create
/design [Feature] add [section] → Add specific section
/design [Feature] improve → Suggest improvements
```
---
## Model Recommendation
**This command is optimized for Opus** for complex architectural decisions and comprehensive specification writing.
---
## Key Files
```
claude-product-cycle/design-spec-layer/
├── STATUS.md # All features status
├── _shared/
│ ├── PATTERNS.md # Implementation patterns
│ └── API_REFERENCE.md # Fineract API reference
└── features/[feature]/
├── SPEC.md # What to build (UI, flows)
├── API.md # APIs needed
└── STATUS.md # Feature implementation status
```
---
## Workflow
```
┌───────────────────────────────────────────────────────────────────┐
│ /design [Feature] WORKFLOW │
├───────────────────────────────────────────────────────────────────┤
│ │
│ STEP 1: GATHER CONTEXT │
│ ├─→ Read claude-product-cycle/design-spec-layer/STATUS.md │
│ ├─→ Read features/[feature]/SPEC.md (if exists) │
│ ├─→ Read features/[feature]/API.md (if exists) │
│ ├─→ Read actual code in feature/[feature]/ │
│ └─→ Read server-layer/FINERACT_API.md │
│ │
│ STEP 2: ANALYZE │
│ ├─→ Compare current spec vs implementation │
│ ├─→ Identify gaps, outdated sections, missing features │
│ ├─→ Research best practices for similar apps │
│ └─→ Report findings to user │
│ │
│ STEP 3: UPDATE SPEC.md │
│ ├─→ Update/add sections with ASCII mockups │
│ ├─→ Define state model │
│ ├─→ Define user actions │
│ └─→ Add changelog entry │
│ │
│ STEP 4: UPDATE API.md │
│ ├─→ List all required endpoints │
│ ├─→ Define request/response structures │
│ └─→ Note any missing endpoints │
│ │
│ STEP 5: CROSS-UPDATE (MANDATORY) │
│ ├─→ features/[feature]/STATUS.md │
│ └─→ claude-product-cycle/design-spec-layer/STATUS.md │
│ │
│ STEP 6: GENERATE IMPLEMENTATION SUMMARY │
│ └─→ Output clear requirements for /implement │
│ │
└───────────────────────────────────────────────────────────────────┘
```
---
## SPEC.md Template
```markdown
# [Feature Name] - Feature Specification
> **Purpose**: [One-line description]
> **User Value**: [Why users need this]
> **Last Updated**: [Date]
---
## 1. Overview
### 1.1 Feature Summary
[2-3 sentences describing the feature]
### 1.2 User Stories
- As a user, I want to [action] so that [benefit]
---
## 2. Screen Layout
### 2.1 ASCII Mockup
```
┌─────────────────────────────────────────┐
│ ← Back [Title] ⋮ │ ← TopBar
├─────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ │
│ │ Section 1 │ │
│ └─────────────────────────────────┘ │
│ │
└─────────────────────────────────────────┘
```
### 2.2 Sections Table
| # | Section | Description | API | Priority |
|---|---------|-------------|-----|----------|
| 1 | [Name] | [What it shows] | [Endpoint] | P0 |
---
## 3. User Interactions
| Action | Trigger | Result | API Call |
|--------|---------|--------|----------|
| Tap item | Click | Navigate | - |
| Pull refresh | Swipe down | Reload data | [Endpoint] |
---
## 4. State Model
```kotlin
@Immutable
data class [Feature]State(
val isLoading: Boolean = false,
val data: List<Item> = emptyList(),
val error: String? = null,
)
sealed interface [Feature]ScreenState {
data object Loading : [Feature]ScreenState
data object Success : [Feature]ScreenState
data class Error(val message: StringResource) : [Feature]ScreenState
}
```
---
## 5. API Requirements
| Endpoint | Method | Purpose | Status |
|----------|--------|---------|--------|
| /self/[path] | GET | [Description] | ✅ Exists |
---
## 6. Edge Cases & Error Handling
| Scenario | Behavior | UI Feedback |
|----------|----------|-------------|
| No internet | Show cached | Toast |
| Empty results | Show empty state | Illustration |
| API error | Retry logic | Snackbar |
---
## Changelog
| Date | Change |
|------|--------|
| [date] | Initial spec |
```
---
## API.md Template
```markdown
# [Feature Name] - API Reference
## Endpoints Required
### [Endpoint Name]
**Endpoint**: `GET /self/[path]`
**Description**: [What this endpoint does]
**Request**:
```
Headers:
Authorization: Basic {token}
Fineract-Platform-TenantId: {tenant}
```
**Response**:
```json
{
"field": "value"
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class [Name]Dto(
@SerialName("field") val field: String,
)
```
**Status**: ✅ Implemented / ❌ Missing
---
## API Summary
| Endpoint | Service | Repository | Status |
|----------|---------|------------|--------|
| /self/[path] | [Name]Service | [Name]Repository | ✅ |
```
---
## Output Template
After completing design, output:
```
┌───────────────────────────────────────────────────────────────────┐
│ IMPLEMENTATION REQUIREMENTS │
│ Ready for /implement in Sonnet session │
├───────────────────────────────────────────────────────────────────┤
│ │
│ FEATURE: [Feature Name] │
│ SPEC UPDATED: features/[feature]/SPEC.md │
│ │
│ ════════════════════════════════════════════════════════════════ │
│ │
│ CLIENT WORK NEEDED: │
│ [ ] Network: [DTO/Service changes] │
│ [ ] Data: [Repository changes] │
│ │
│ FEATURE WORK NEEDED: │
│ [ ] ViewModel: [changes] │
│ [ ] Screen: [changes] │
│ [ ] Components: [new components] │
│ │
│ ════════════════════════════════════════════════════════════════ │
│ │
│ NEXT STEP: │
│ Run: /implement [Feature] │
│ │
└───────────────────────────────────────────────────────────────────┘
```
---
## If No Feature Name Provided
Show feature list:
```
📋 FEATURES AVAILABLE FOR DESIGN:
| Feature | Status | Last Updated | Command |
|---------|--------|--------------|---------|
| auth | ✅ Done | - | /design auth |
| home | ✅ Done | - | /design home |
| accounts | ✅ Done | - | /design accounts |
| loan-account | ✅ Done | - | /design loan-account |
| savings-account | ✅ Done | - | /design savings-account |
| share-account | ✅ Done | - | /design share-account |
| beneficiary | ✅ Done | - | /design beneficiary |
| transfer | ✅ Done | - | /design transfer |
| recent-transaction | ✅ Done | - | /design recent-transaction |
| notification | ✅ Done | - | /design notification |
| settings | ✅ Done | - | /design settings |
| passcode | ✅ Done | - | /design passcode |
| guarantor | ✅ Done | - | /design guarantor |
| qr | ✅ Done | - | /design qr |
| location | ✅ Done | - | /design location |
| client-charge | ✅ Done | - | /design client-charge |
Which feature do you want to design?
```

View File

@ -1,254 +0,0 @@
# /feature - Feature/UI Layer Implementation
## Purpose
Implement the feature/UI layer including ViewModel, Screen, Components, and Navigation.
---
## Workflow
```
┌───────────────────────────────────────────────────────────────────┐
│ /feature [Feature] WORKFLOW │
├───────────────────────────────────────────────────────────────────┤
│ │
│ STEP 1: READ SPEC │
│ ├─→ Read features/[feature]/SPEC.md │
│ ├─→ Extract UI sections, state model, user actions │
│ └─→ Read _shared/PATTERNS.md for MVI pattern │
│ │
│ STEP 2: CHECK PREREQUISITES │
│ ├─→ Verify client layer exists (Repository) │
│ └─→ If missing, suggest: /client [Feature] first │
│ │
│ STEP 3: CREATE VIEWMODEL │
│ ├─→ Define State data class │
│ ├─→ Define Event sealed interface │
│ ├─→ Define Action sealed interface │
│ ├─→ Implement handleAction() │
│ └─→ Implement data loading logic │
│ │
│ STEP 4: CREATE SCREEN │
│ ├─→ Create main Screen composable │
│ ├─→ Handle state rendering │
│ ├─→ Handle event collection │
│ └─→ Connect to ViewModel actions │
│ │
│ STEP 5: CREATE COMPONENTS │
│ ├─→ Extract reusable components │
│ └─→ Add @Preview annotations │
│ │
│ STEP 6: CREATE NAVIGATION │
│ ├─→ Define navigation route │
│ └─→ Register in navigation graph │
│ │
│ STEP 7: REGISTER DI │
│ ├─→ Create [Feature]Module.kt │
│ └─→ Register ViewModel │
│ │
│ STEP 8: BUILD & VERIFY │
│ ├─→ ./gradlew :feature:[name]:build │
│ └─→ ./gradlew spotlessApply detekt │
│ │
└───────────────────────────────────────────────────────────────────┘
```
---
## File Locations
```
feature/[name]/src/commonMain/kotlin/org/mifos/mobile/feature/[name]/
├── [Feature]ViewModel.kt # MVI ViewModel
├── [Feature]Screen.kt # Main screen composable
├── components/ # UI components
│ └── [Component].kt
├── navigation/
│ └── [Feature]Navigation.kt # Navigation definition
└── di/
└── [Feature]Module.kt # Koin module
```
---
## ViewModel Pattern (MVI)
```kotlin
internal class [Feature]ViewModel(
private val repository: [Feature]Repository,
) : BaseViewModel<[Feature]State, [Feature]Event, [Feature]Action>(
initialState = [Feature]State()
) {
init {
loadData()
}
override fun handleAction(action: [Feature]Action) {
when (action) {
is [Feature]Action.Retry -> loadData()
is [Feature]Action.OnItemClick -> handleItemClick(action.id)
}
}
private fun loadData() {
viewModelScope.launch {
repository.getData()
.collect { dataState ->
when (dataState) {
is DataState.Loading -> updateState {
it.copy(uiState = [Feature]ScreenState.Loading)
}
is DataState.Success -> updateState {
it.copy(
uiState = [Feature]ScreenState.Success,
data = dataState.data
)
}
is DataState.Error -> updateState {
it.copy(uiState = [Feature]ScreenState.Error(dataState.message))
}
}
}
}
}
private fun handleItemClick(id: Long) {
sendEvent([Feature]Event.NavigateToDetail(id))
}
}
// State
@Immutable
data class [Feature]State(
val data: List<Item> = emptyList(),
val uiState: [Feature]ScreenState = [Feature]ScreenState.Loading,
)
sealed interface [Feature]ScreenState {
data object Loading : [Feature]ScreenState
data object Success : [Feature]ScreenState
data class Error(val message: String) : [Feature]ScreenState
}
// Events (one-time navigation/toasts)
sealed interface [Feature]Event {
data class NavigateToDetail(val id: Long) : [Feature]Event
data object NavigateBack : [Feature]Event
}
// Actions (user interactions)
sealed interface [Feature]Action {
data object Retry : [Feature]Action
data class OnItemClick(val id: Long) : [Feature]Action
}
```
---
## Screen Pattern
```kotlin
@Composable
fun [Feature]Screen(
viewModel: [Feature]ViewModel = koinViewModel(),
onNavigateBack: () -> Unit,
onNavigateToDetail: (Long) -> Unit,
) {
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
// Handle one-time events
LaunchedEffect(Unit) {
viewModel.eventFlow.collect { event ->
when (event) {
is [Feature]Event.NavigateBack -> onNavigateBack()
is [Feature]Event.NavigateToDetail -> onNavigateToDetail(event.id)
}
}
}
[Feature]Content(
state = state,
onAction = viewModel::sendAction,
)
}
@Composable
private fun [Feature]Content(
state: [Feature]State,
onAction: ([Feature]Action) -> Unit,
) {
when (state.uiState) {
is [Feature]ScreenState.Loading -> LoadingContent()
is [Feature]ScreenState.Success -> SuccessContent(
data = state.data,
onItemClick = { onAction([Feature]Action.OnItemClick(it)) }
)
is [Feature]ScreenState.Error -> ErrorContent(
message = state.uiState.message,
onRetry = { onAction([Feature]Action.Retry) }
)
}
}
```
---
## Navigation Pattern
```kotlin
// Navigation definition
fun NavGraphBuilder.[feature]Screen(
onNavigateBack: () -> Unit,
onNavigateToDetail: (Long) -> Unit,
) {
composable<[Feature]Route> {
[Feature]Screen(
onNavigateBack = onNavigateBack,
onNavigateToDetail = onNavigateToDetail,
)
}
}
// Route
@Serializable
data object [Feature]Route
```
---
## DI Module Pattern
```kotlin
val [feature]Module = module {
viewModelOf(::[Feature]ViewModel)
}
```
---
## Output Template
```
┌──────────────────────────────────────────────────────────────────────┐
│ ✅ FEATURE LAYER COMPLETE │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ Created/Updated: │
│ ├─ feature/[name]/[Feature]ViewModel.kt │
│ ├─ feature/[name]/[Feature]Screen.kt │
│ ├─ feature/[name]/components/*.kt │
│ ├─ feature/[name]/navigation/[Feature]Navigation.kt │
│ └─ feature/[name]/di/[Feature]Module.kt │
│ │
│ Navigation: │
│ └─ Route registered ✅ │
│ │
│ 🔨 BUILD: :feature:[name] ✅ │
│ 🧹 LINT: spotlessApply ✅ detekt ✅ │
│ │
├──────────────────────────────────────────────────────────────────────┤
│ NEXT STEP: │
│ Run: /verify [Feature] │
└──────────────────────────────────────────────────────────────────────┘
```

View File

@ -1,237 +0,0 @@
# /implement - E2E Feature Implementation
## Purpose
Full end-to-end implementation of a feature including client layer (Network + Data) and feature layer (UI).
---
## Command Variants
```
/implement → Show feature status list
/implement [Feature] → Full E2E implementation
/implement [Feature] --quick → Skip validations
/implement [Feature] --no-git → Skip git integration
/implement improve [Feature] → Improve existing feature
```
---
## E2E Pipeline
```
┌─────────────────────────────────────────────────────────────────────┐
│ /implement [Feature] - E2E AUTOMATED PIPELINE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ✅ Git Integration - Auto branch, commits after each phase │
│ ✅ Dependency Check - Validate all dependencies before start │
│ ✅ Auto-Build - Gradle build after each layer │
│ ✅ Lint & Format - Run detekt, spotless │
│ ✅ Checkpoints - Review/improve after each layer │
│ ✅ Progress Dashboard - Real-time progress tracking │
│ │
│ FULL PIPELINE: │
│ ┌───────┐ ┌────────┐ ┌────────┐ ┌─────────┐ ┌───────┐ │
│ │ GIT │─▶│VALIDATE│─▶│ CLIENT │─▶│ FEATURE │─▶│ BUILD │ │
│ └───────┘ └────────┘ └───┬────┘ └────┬────┘ └───┬───┘ │
│ branch deps │ │ │ │
│ [checkpoint] [checkpoint] [commit] │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## Key Files
1. `claude-product-cycle/design-spec-layer/features/[feature]/SPEC.md` - What to build
2. `claude-product-cycle/design-spec-layer/features/[feature]/API.md` - APIs needed
3. `claude-product-cycle/design-spec-layer/_shared/PATTERNS.md` - Implementation patterns
---
## Implementation Flow
```
┌─────────────────────────────────────────────────────────────────────┐
│ E2E IMPLEMENTATION PIPELINE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ PHASE 0: GIT SETUP │
│ ├─→ Check working directory is clean │
│ ├─→ Create branch: git checkout -b feature/{name} │
│ └─→ [AUTO-CONTINUE] │
│ │
│ PHASE 1: DEPENDENCY VALIDATION │
│ ├─→ Read SPEC.md + API.md │
│ ├─→ Check required services exist │
│ ├─→ Check Kotlin dependencies available │
│ ├─→ Identify gaps │
│ └─→ [AUTO-CONTINUE if all deps satisfied] │
│ │
│ PHASE 2: CLIENT LAYER │
│ ├─→ Create/update DTOs in core/network/model/ (if needed) │
│ ├─→ Create/update Service in core/network/services/ │
│ ├─→ Create/update Repository in core/data/repository/ │
│ ├─→ Register in DI modules │
│ ├─→ 🔨 BUILD: ./gradlew :core:network:build :core:data:build │
│ ├─→ 🧹 LINT: spotlessApply │
│ ├─→ 📝 COMMIT: git commit -m "feat({name}): Add client layer" │
│ └─→ ⏸️ CHECKPOINT: Client Summary + Options │
│ │
│ PHASE 3: FEATURE LAYER │
│ ├─→ Create ViewModel (State, Event, Action) │
│ ├─→ Create Screen (Compose UI) │
│ ├─→ Create Components │
│ ├─→ Create Navigation │
│ ├─→ Register in DI module │
│ ├─→ 🔨 BUILD: ./gradlew :feature:{name}:build │
│ ├─→ 🧹 LINT: spotlessApply detekt │
│ ├─→ 📝 COMMIT: git commit -m "feat({name}): Add feature layer" │
│ └─→ ⏸️ CHECKPOINT: Feature Summary + Options │
│ │
│ PHASE 4: FINALIZE │
│ ├─→ Update feature's STATUS.md │
│ ├─→ Update main STATUS.md │
│ ├─→ 🔨 FINAL BUILD: ./gradlew build │
│ └─→ 📝 COMMIT: git commit -m "docs({name}): Update status" │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## Checkpoint Templates
### After CLIENT Layer:
```
┌──────────────────────────────────────────────────────────────────────┐
│ ✅ CLIENT LAYER COMPLETE │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ Created/Updated Files: │
│ ├─ core/network/model/[Feature]Dto.kt │
│ ├─ core/network/services/[Feature]Service.kt │
│ ├─ core/data/repository/[Feature]Repository.kt │
│ └─ core/data/repositoryImpl/[Feature]RepositoryImpl.kt │
│ │
│ Registered in DI: │
│ ├─ NetworkModule: [Feature]Service ✅ │
│ └─ DataModule: [Feature]Repository ✅ │
│ │
│ 🔨 BUILD: :core:network ✅ :core:data ✅ │
│ 🧹 LINT: spotlessApply ✅ │
│ 📝 COMMIT: feat([feature]): Add client layer │
│ │
├──────────────────────────────────────────────────────────────────────┤
│ Options: │
│ • c / continue → Proceed to FEATURE layer │
│ • i / improve → Describe what to improve │
│ • v / view → Show file content │
└──────────────────────────────────────────────────────────────────────┘
```
### After FEATURE Layer:
```
┌──────────────────────────────────────────────────────────────────────┐
│ ✅ FEATURE LAYER COMPLETE │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ Created/Updated Files: │
│ ├─ feature/[name]/[Feature]ViewModel.kt │
│ ├─ feature/[name]/[Feature]Screen.kt │
│ ├─ feature/[name]/components/*.kt │
│ ├─ feature/[name]/navigation/[Feature]Navigation.kt │
│ └─ feature/[name]/di/[Feature]Module.kt │
│ │
│ Navigation: │
│ └─ Route registered ✅ │
│ │
│ 🔨 BUILD: :feature:[name] ✅ │
│ 🧹 LINT: spotlessApply ✅ detekt ✅ │
│ 📝 COMMIT: feat([feature]): Add feature layer │
│ │
├──────────────────────────────────────────────────────────────────────┤
│ Options: │
│ • c / continue → Complete implementation, update status │
│ • i / improve → Describe improvement │
│ • v / view [file] → Show specific file content │
└──────────────────────────────────────────────────────────────────────┘
```
---
## Final Report Template
```
╔══════════════════════════════════════════════════════════════════════╗
║ /implement [Feature] - COMPLETE ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ ✅ PHASE 0: GIT SETUP ║
║ └─ Branch: feature/[name] ║
║ ║
║ ✅ PHASE 1: DEPENDENCY VALIDATION ║
║ └─ All dependencies satisfied ║
║ ║
║ ✅ PHASE 2: CLIENT LAYER ║
║ ├─ Files: [count] created/updated ║
║ ├─ Build: :core:network ✅ :core:data ✅ ║
║ └─ Commit: feat([feature]): Add client layer ║
║ ║
║ ✅ PHASE 3: FEATURE LAYER ║
║ ├─ Files: [count] created/updated ║
║ ├─ Build: :feature:[name] ✅ ║
║ └─ Commit: feat([feature]): Add feature layer ║
║ ║
║ ✅ PHASE 4: FINALIZE ║
║ ├─ Updated: STATUS.md ║
║ ├─ Final Build: ./gradlew build ✅ ║
║ └─ Commit: docs([feature]): Update status ║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ 📊 SUMMARY ║
║ ├─ Files: +[count] created, ~[count] modified ║
║ ├─ Commits: [count] ║
║ └─ Errors: 0 ║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ 🎉 IMPLEMENTATION COMPLETE ║
║ ║
║ Next steps: ║
║ • Push branch: git push -u origin feature/[name] ║
║ • Create PR: gh pr create ║
║ • Verify: /verify [Feature] ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
```
---
## Cross-Update Rules
After ANY implementation:
1. Update feature's `STATUS.md`
2. Update main `claude-product-cycle/design-spec-layer/STATUS.md`
3. Add changelog entries
---
## If No Feature Name Provided
Show feature list:
```
📋 FEATURES AVAILABLE FOR IMPLEMENTATION:
| Feature | Status | Client | Feature | Command |
|---------|--------|--------|---------|---------|
| auth | ✅ Done | ✅ | ✅ | /implement auth |
| home | ✅ Done | ✅ | ✅ | /implement home |
...
Which feature do you want to implement?
```

View File

@ -1,409 +0,0 @@
# /mockup - Design Mockup Generation
## Purpose
Generate visual design mockups from feature specifications using Figma plugin or AI tool prompts.
---
## Command Variants
```
/mockup → Show available features
/mockup [Feature] → Generate Figma plugin code
/mockup [Feature] prompts → Generate AI tool prompts
/mockup [Feature] tokens → Generate design tokens JSON
/mockup sync → Update mockup status across features
```
---
## Model Recommendation
**This command works well with both Sonnet and Opus**. Sonnet for quick prompt generation, Opus for complex multi-screen mockups.
---
## MCP Connection Check (IMPORTANT)
Before generating mockups, CHECK if Figma MCP is connected. If not, prompt user:
```
┌───────────────────────────────────────────────────────────────────┐
│ ⚠️ FIGMA MCP NOT CONNECTED │
├───────────────────────────────────────────────────────────────────┤
│ │
│ Figma MCP enables: │
│ • Direct design-to-code workflow │
│ • Reading Figma frames for implementation │
│ • Better design accuracy │
│ │
│ OPTIONS: │
│ │
│ [1] Connect Figma MCP now (Recommended) │
│ → Run: claude mcp add figma https://mcp.figma.com/mcp │
│ → Requires Figma account authentication │
│ │
│ [2] Skip - Continue with manual workflow │
│ → Generate prompts/plugin code │
│ → Manually export to Figma later │
│ → Connect MCP before /implement │
│ │
│ [3] Cancel │
│ │
└───────────────────────────────────────────────────────────────────┘
Which option do you prefer?
```
### Connection Commands Reference
```bash
# Figma MCP (for design-to-code)
claude mcp add figma https://mcp.figma.com/mcp
# Check connected MCPs
claude mcp list
# Remove MCP
claude mcp remove figma
```
### When to Check MCP
| Command Variant | MCP Required | Check Timing |
|-----------------|--------------|--------------|
| `/mockup [feature]` | Optional | After generation |
| `/mockup [feature] prompts` | Optional | After generation |
| `/mockup [feature] tokens` | No | Skip check |
| Before `/implement` | Yes | Must connect |
---
## Key Files
```
claude-product-cycle/mockup-layer/
├── LAYER_STATUS.md # Mockup layer status
├── README.md # Usage documentation
├── figma-plugin/ # Figma plugin source
│ ├── package.json
│ ├── manifest.json
│ └── src/
│ ├── plugin.ts # Main plugin entry
│ ├── design-system/ # Material Design 3 tokens
│ │ └── tokens.ts
│ ├── generators/ # Component generators
│ │ └── components/
│ └── utils/
│ └── helpers.ts
├── scripts/ # Build scripts
└── templates/ # Prompt templates
claude-product-cycle/design-spec-layer/features/[feature]/
├── SPEC.md # Source specification
├── API.md # API documentation
└── mockups/ # Generated mockups (NEW)
├── PROMPTS.md # AI tool prompts
├── figma-generator.ts # Feature-specific Figma code
└── design-tokens.json # Feature design tokens
```
---
## Workflow
```
┌───────────────────────────────────────────────────────────────────┐
│ /mockup [Feature] WORKFLOW │
├───────────────────────────────────────────────────────────────────┤
│ │
│ STEP 1: READ SPECIFICATION │
│ ├─→ Read features/[feature]/SPEC.md │
│ ├─→ Parse ASCII mockups section │
│ ├─→ Extract component definitions │
│ └─→ Identify screen layout structure │
│ │
│ STEP 2: ANALYZE COMPONENTS │
│ ├─→ Map ASCII elements to Material Design 3 components │
│ ├─→ Identify custom components needed │
│ ├─→ Determine color/typography tokens │
│ └─→ List required generators │
│ │
│ STEP 3: GENERATE OUTPUT (based on variant) │
│ │ │
│ │ [Default: Figma Plugin] │
│ │ ├─→ Generate TypeScript code using generators │
│ │ ├─→ Output to features/[feature]/mockups/figma-generator.ts │
│ │ └─→ Instructions to run in Figma │
│ │ │
│ │ [prompts variant] │
│ │ ├─→ Generate detailed prompts for AI tools │
│ │ ├─→ Output to features/[feature]/mockups/PROMPTS.md │
│ │ └─→ Include Google Stitch, Uizard, Visily formats │
│ │ │
│ │ [tokens variant] │
│ │ ├─→ Extract design tokens from SPEC │
│ │ ├─→ Output to features/[feature]/mockups/design-tokens.json │
│ │ └─→ Include colors, typography, spacing │
│ │ │
│ STEP 4: UPDATE STATUS │
│ ├─→ Update mockup-layer/LAYER_STATUS.md │
│ └─→ Add mockup status to feature table │
│ │
│ STEP 5: OUTPUT NEXT STEPS │
│ └─→ Instructions to use generated output │
│ │
└───────────────────────────────────────────────────────────────────┘
```
---
## PROMPTS.md Template
```markdown
# [Feature Name] - AI Mockup Prompts
> Generated from: features/[feature]/SPEC.md
> Generated on: [Date]
---
## Screen 1: [Screen Name]
### Google Stitch / Visily Prompt
```
Create a [screen type] mobile screen with Material Design 3:
**Header:**
- [Component description]
**Main Content:**
- [Section 1]: [Description]
- [Section 2]: [Description]
**Footer:**
- [Component description]
**Style Guidelines:**
- Color scheme: Purple primary (#6750A4), white surface
- Typography: Inter font family
- Spacing: 16px standard padding
- Platform: Android mobile app (393x852)
```
### Uizard Prompt
```
Design a mobile banking app screen showing:
1. [Key element 1]
2. [Key element 2]
3. [Key element 3]
Style: Modern, clean, Material Design 3
Colors: Purple accent on white background
```
---
## Component Prompts
### [Component Name]
```
[Detailed prompt for individual component]
```
---
## Export Instructions
1. Generate design in [AI Tool]
2. Export to Figma (if available)
3. Connect Figma MCP to Claude Code
4. Run /implement [feature] for code generation
```
---
## figma-generator.ts Template
```typescript
/**
* [Feature Name] - Figma Mockup Generator
* Generated from: features/[feature]/SPEC.md
*/
import {
createScreen,
createTopBar,
createBottomNav,
createCard,
// ... other imports
} from '../../mockup-layer/figma-plugin/src/generators'
export async function generate[Feature]Screen(): Promise<FrameNode> {
const screen = createScreen({
name: '[Feature] Screen',
hasTopBar: true,
hasBottomNav: true,
})
// Add components based on SPEC.md
// ...
return screen
}
```
---
## design-tokens.json Template
```json
{
"feature": "[Feature Name]",
"generated": "[Date]",
"tokens": {
"colors": {
"primary": "#6750A4",
"surface": "#FFFBFE",
"custom": {}
},
"typography": {
"headline": { "size": 28, "weight": 400 },
"body": { "size": 16, "weight": 400 }
},
"spacing": {
"screen": 16,
"section": 24,
"component": 8
},
"components": [
{
"name": "[Component]",
"type": "card|list|button|input",
"properties": {}
}
]
}
}
```
---
## Output Template
After generating mockup assets, output:
```
┌───────────────────────────────────────────────────────────────────┐
│ MOCKUP GENERATION COMPLETE │
├───────────────────────────────────────────────────────────────────┤
│ │
│ FEATURE: [Feature Name] │
│ SOURCE: features/[feature]/SPEC.md │
│ │
│ ════════════════════════════════════════════════════════════════ │
│ │
│ GENERATED FILES: │
│ ✅ features/[feature]/mockups/PROMPTS.md │
│ ✅ features/[feature]/mockups/figma-generator.ts │
│ ✅ features/[feature]/mockups/design-tokens.json │
│ │
│ ════════════════════════════════════════════════════════════════ │
│ │
│ OPTION A: FIGMA PLUGIN │
│ 1. cd claude-product-cycle/mockup-layer/figma-plugin │
│ 2. npm install && npm run build │
│ 3. In Figma: Plugins → Development → Import manifest │
│ 4. Run: Plugins → Mifos Mockup Generator → Generate [Feature] │
│ │
│ OPTION B: AI TOOL │
│ 1. Open features/[feature]/mockups/PROMPTS.md │
│ 2. Copy prompt for Google Stitch / Uizard / Visily │
│ 3. Generate and export to Figma │
│ │
│ ════════════════════════════════════════════════════════════════ │
│ │
│ AFTER MOCKUP IS IN FIGMA: │
│ 1. Connect Figma MCP: claude mcp add figma https://mcp.figma.com │
│ 2. Run: /implement [feature] │
│ │
└───────────────────────────────────────────────────────────────────┘
```
---
## If No Feature Name Provided
Show available features:
```
🎨 FEATURES AVAILABLE FOR MOCKUP GENERATION:
| Feature | SPEC | Mockup Status | Command |
|---------|------|---------------|---------|
| dashboard | ✅ | 📋 Planned | /mockup dashboard |
| auth | ✅ | - | /mockup auth |
| home | ✅ | - | /mockup home |
| accounts | ✅ | - | /mockup accounts |
| ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
COMMAND VARIANTS:
/mockup [feature] Generate Figma plugin code
/mockup [feature] prompts Generate AI tool prompts
/mockup [feature] tokens Generate design tokens JSON
Which feature do you want to generate mockups for?
```
---
## Component Mapping Reference
| ASCII Element | Material Design 3 | Generator Function |
|---------------|-------------------|-------------------|
| `[Title]` | Top App Bar | `createTopBar()` |
| `┌───┐` box | Card | `createCard()` |
| `[Button]` | Filled Button | `createButton()` |
| `[___]` | Text Field | `createInputField()` |
| `• Item` | List Item | `createListItem()` |
| `[🏠][📊]` | Bottom Nav | `createBottomNav()` |
| `[Icon] Label` | Quick Action | `createQuickActions()` |
---
## Design System Reference
### Colors (Material Design 3)
```
Primary: #6750A4
OnPrimary: #FFFFFF
Surface: #FFFBFE
OnSurface: #1C1B1F
Error: #B3261E
Success: #2E7D32
```
### Typography
```
Display Large: 57px / 400
Headline Medium: 28px / 400
Title Large: 22px / 400
Body Large: 16px / 400
Label Medium: 12px / 500
```
### Spacing
```
xs: 4px | sm: 8px | md: 16px | lg: 24px | xl: 32px
```
### Screen Dimensions
```
Mobile: 393 x 852
Mobile Large: 430 x 932
Tablet: 768 x 1024
```

View File

@ -1,115 +0,0 @@
# /projectstatus - Project Overview
## Purpose
Display the current state of the Mifos Mobile project, including feature implementation status, available commands, and suggested next steps.
---
## Workflow
```
┌───────────────────────────────────────────────────────────────────┐
│ /projectstatus WORKFLOW │
├───────────────────────────────────────────────────────────────────┤
│ │
│ STEP 1: READ STATUS FILES │
│ ├─→ claude-product-cycle/design-spec-layer/STATUS.md │
│ └─→ Individual feature STATUS.md files │
│ │
│ STEP 2: ANALYZE CODEBASE │
│ ├─→ Check feature/ directory for implemented features │
│ ├─→ Check core/network/services/ for API services │
│ ├─→ Check core/data/repository/ for repositories │
│ └─→ Compare spec vs implementation │
│ │
│ STEP 3: GENERATE DASHBOARD │
│ ├─→ Feature status table │
│ ├─→ Layer completion summary │
│ ├─→ Available commands │
│ └─→ Suggested next steps │
│ │
└───────────────────────────────────────────────────────────────────┘
```
---
## Output Template
```
╔══════════════════════════════════════════════════════════════════════╗
║ MIFOS MOBILE - PROJECT STATUS ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ PROJECT: Mifos Mobile (Self-Service Banking App) ║
║ TECH STACK: Kotlin Multiplatform + Compose + Fineract API ║
║ LAST UPDATED: [Date] ║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ FEATURE STATUS ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ | Feature | Status | Client | Feature | Gaps | ║
║ |-------------------|------------|--------|---------|------| ║
║ | Auth | ✅ Done | ✅ | ✅ | 0 | ║
║ | Home | ✅ Done | ✅ | ✅ | 0 | ║
║ | Accounts | ✅ Done | ✅ | ✅ | 0 | ║
║ | Loan Account | ✅ Done | ✅ | ✅ | 0 | ║
║ | Savings Account | ✅ Done | ✅ | ✅ | 0 | ║
║ | Share Account | ✅ Done | ✅ | ✅ | 0 | ║
║ | Beneficiary | ✅ Done | ✅ | ✅ | 0 | ║
║ | Transfer | ✅ Done | ✅ | ✅ | 0 | ║
║ | Recent Transaction| ✅ Done | ✅ | ✅ | 0 | ║
║ | Notification | ✅ Done | ✅ | ✅ | 0 | ║
║ | Settings | ✅ Done | ✅ | ✅ | 0 | ║
║ | Passcode | ✅ Done | - | ✅ | 0 | ║
║ | Guarantor | ✅ Done | ✅ | ✅ | 0 | ║
║ | QR Code | ✅ Done | - | ✅ | 0 | ║
║ | Location | ✅ Done | - | ✅ | 0 | ║
║ | Client Charges | ✅ Done | ✅ | ✅ | 0 | ║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ AVAILABLE COMMANDS ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ Design: ║
║ /design [Feature] → Create/update feature specification ║
║ ║
║ Implement: ║
║ /implement [Feature] → Full E2E implementation ║
║ /client [Feature] → Network + Data layers ║
║ /feature [Feature] → UI layer (ViewModel + Screen) ║
║ ║
║ Verify: ║
║ /verify [Feature] → Validate implementation vs spec ║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ SUGGESTED NEXT STEPS ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ 1. Review existing features: /verify [Feature] ║
║ 2. Improve feature: /design [Feature] for enhancements ║
║ 3. Add new feature: /design [NewFeature] ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
```
---
## Key Files to Read
1. `claude-product-cycle/design-spec-layer/STATUS.md` - Master status tracker
2. `feature/*/` - Feature module directories
3. `core/network/services/` - API services
4. `core/data/repository/` - Repositories
---
## Status Legend
| Status | Meaning |
|--------|---------|
| ✅ Done | Feature complete, all working |
| ⚠️ Needs Update | Has gaps, spec changed, or incomplete |
| 🔄 In Progress | Currently being implemented |
| 📋 Planned | Spec exists, not started |
| 🆕 Not Started | No work done |

View File

@ -1,169 +0,0 @@
# /verify - Implementation Verification
## Purpose
Validate that the implementation matches the specification. Identify gaps between SPEC.md and actual code.
---
## Workflow
```
┌───────────────────────────────────────────────────────────────────┐
│ /verify [Feature] WORKFLOW │
├───────────────────────────────────────────────────────────────────┤
│ │
│ PHASE 1: READ SPEC │
│ ├─→ Read features/[feature]/SPEC.md │
│ ├─→ Extract all UI sections │
│ ├─→ Extract all user actions │
│ ├─→ Extract state model │
│ └─→ Extract API requirements │
│ │
│ PHASE 2: CHECK ACTUAL CODE │
│ ├─→ Read feature/[name]/*ViewModel.kt │
│ ├─→ Read feature/[name]/*Screen.kt │
│ ├─→ Read feature/[name]/components/*.kt │
│ ├─→ Read core/network/services/*Service.kt │
│ └─→ Read core/data/repository/*Repository.kt │
│ │
│ PHASE 3: COMPARE SPEC VS CODE │
│ ├─→ All sections from spec implemented? │
│ ├─→ All user actions handled? │
│ ├─→ State model matches? │
│ ├─→ All API calls present? │
│ └─→ DI registration complete? │
│ │
│ PHASE 4: CHECK LAYER INTEGRITY │
│ ├─→ Network → Data → Feature flow correct? │
│ ├─→ No layer violations? │
│ └─→ Navigation configured? │
│ │
│ PHASE 5: GENERATE REPORT │
│ ├─→ List all gaps found │
│ ├─→ List suggestions for improvement │
│ └─→ Output: Gap report or "✅ Feature verified" │
│ │
└───────────────────────────────────────────────────────────────────┘
```
---
## Verification Checklist
### UI Sections
- [ ] All sections from SPEC.md ASCII mockup present in Screen
- [ ] Loading state handled
- [ ] Error state handled
- [ ] Empty state handled (if applicable)
### User Actions
- [ ] All actions from SPEC.md handled in ViewModel
- [ ] Actions trigger correct events/state changes
- [ ] Navigation works correctly
### State Model
- [ ] State class matches SPEC.md definition
- [ ] All required fields present
- [ ] Correct default values
### API Integration
- [ ] All required endpoints called
- [ ] Error handling for API failures
- [ ] Loading states during API calls
### DI Registration
- [ ] ViewModel registered in module
- [ ] Repository registered in module
- [ ] Service registered in module
### Navigation
- [ ] Route defined
- [ ] Screen registered in nav graph
- [ ] Navigation parameters correct
---
## Output Templates
### All Good:
```
╔══════════════════════════════════════════════════════════════════════╗
║ ✅ VERIFICATION COMPLETE - [Feature] ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ UI SECTIONS: ✅ All 5 sections implemented ║
║ USER ACTIONS: ✅ All 8 actions handled ║
║ STATE MODEL: ✅ Matches specification ║
║ API INTEGRATION: ✅ All 3 endpoints called ║
║ DI REGISTRATION: ✅ Complete ║
║ NAVIGATION: ✅ Configured ║
║ ║
║ RESULT: Feature fully implements specification ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
```
### Gaps Found:
```
╔══════════════════════════════════════════════════════════════════════╗
║ ⚠️ VERIFICATION COMPLETE - GAPS FOUND ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ FEATURE: [Feature] ║
║ SPEC: claude-product-cycle/design-spec-layer/features/[feature]/SPEC.md║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ GAPS IDENTIFIED ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ UI SECTIONS (2 gaps): ║
║ ├─ ❌ Empty state not implemented ║
║ └─ ❌ Pull-to-refresh missing ║
║ ║
║ USER ACTIONS (1 gap): ║
║ └─ ❌ Filter action not handled ║
║ ║
║ API INTEGRATION (1 gap): ║
║ └─ ❌ /self/endpoint not called ║
║ ║
║ TOTAL GAPS: 4 ║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ SUGGESTED FIXES ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ 1. Add EmptyContent composable in Screen ║
║ 2. Add SwipeRefresh wrapper in Screen ║
║ 3. Add FilterAction and handleFilter() in ViewModel ║
║ 4. Add endpoint call in Repository ║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ NEXT STEP ║
║ ║
║ Run: /implement [Feature] ║
║ Or fix gaps manually and run: /verify [Feature] ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
```
---
## Key Files to Compare
| Spec File | Code Files |
|-----------|------------|
| features/[feature]/SPEC.md | feature/[name]/*ViewModel.kt |
| | feature/[name]/*Screen.kt |
| | feature/[name]/components/*.kt |
| features/[feature]/API.md | core/network/services/*Service.kt |
| | core/data/repository/*Repository.kt |
---
## Status Update
After verification, update:
1. `features/[feature]/STATUS.md` - Feature status
2. `claude-product-cycle/design-spec-layer/STATUS.md` - Main tracker

View File

@ -1,352 +0,0 @@
# Component Discovery Guide
> **Purpose**: Fast component lookup with automatic updates
> **Pattern**: Static first → Dynamic fallback → Auto-update
---
## Table of Contents
1. [Lookup Strategy](#lookup-strategy)
2. [Static Component Registry](#static-component-registry)
3. [Dynamic Discovery](#dynamic-discovery)
4. [Naming Conventions](#naming-conventions)
5. [Auto-Update Rules](#auto-update-rules)
6. [Component Placement](#component-placement)
---
## Lookup Strategy
```
┌─────────────────────────────────────────────────────────────────┐
│ STEP 1: Check Static Registry (Fast) │
│ → Look in tables below for existing component │
├─────────────────────────────────────────────────────────────────┤
│ STEP 2: If Not Found → Dynamic Search (Fallback) │
│ → Run discovery commands to find in source │
├─────────────────────────────────────────────────────────────────┤
│ STEP 3: If Found Dynamically → Update Static Registry │
│ → Add new component to appropriate table below │
└─────────────────────────────────────────────────────────────────┘
```
**Why This Pattern:**
- Static lookup is instant (read from file)
- Dynamic search catches new components
- Auto-update keeps registry current
---
## Static Component Registry
### Foundation Components (core-base/designsystem)
**Prefix: `Kpt*`**
#### Components (`component/`)
| Component | Purpose | Usage |
|-----------|---------|-------|
| `KptTopAppBar` | Configurable app bar | Standard/Large/Medium variants |
| `KptShimmerLoadingBox` | Skeleton loading | Loading placeholders |
| `KptSnackbarHost` | Snackbar container | Toast messages |
| `KptAnimationSpecs` | Animation specifications | Standard animations |
| `BounceAnimation` | Bounce effect | Button press feedback |
| `SlideTransition` | Slide animation | Screen transitions |
#### Layouts (`layout/`)
| Layout | Purpose | Usage |
|--------|---------|-------|
| `KptGrid` | Responsive grid | Card grids |
| `KptFlowRow` | Horizontal flow | Tag/chip layouts |
| `KptFlowColumn` | Vertical flow | Wrapping columns |
| `KptStack` | Z-axis stacking | Overlays |
| `KptMasonryGrid` | Masonry layout | Pinterest-style |
| `KptResponsiveLayout` | Adaptive layout | Screen size adaptation |
| `KptSidebarLayout` | Sidebar with content | Navigation drawer |
| `KptSplitPane` | Resizable split | Two-panel layout |
| `AdaptiveListDetailPaneScaffold` | List-detail adaptive | Master-detail |
| `AdaptiveNavigableListDetailScaffold` | Navigable list-detail | Navigable master-detail |
| `AdaptiveNavigableSupportingPaneScaffold` | Supporting pane | Three-pane layout |
| `AdaptiveNavigationSuiteScaffold` | Navigation suite | Adaptive navigation |
#### Theme Tokens
| Token | Access | Values |
|-------|--------|--------|
| Spacing | `KptTheme.spacing.*` | `xs`(4dp), `sm`(8dp), `md`(16dp), `lg`(24dp), `xl`(32dp) |
| Shapes | `KptTheme.shapes.*` | `small`, `medium`, `large` |
| Colors | `KptTheme.colorScheme.*` | Material3 color scheme |
---
### Design System Components (core/designsystem)
**Prefix: `Mifos*`**
| Component | Purpose | Usage |
|-----------|---------|-------|
| `MifosScaffold` | Screen scaffold | Top bar, bottom bar, content |
| `MifosTopAppBar` | App bar | Navigation icon, title, actions |
| `MifosTopBar` | Simple title bar | Title only |
| `MifosButton` | Primary button | Main actions |
| `MifosTextField` | Text input | Form fields |
| `MifosPasswordField` | Password input | Visibility toggle |
| `MifosOtpTextField` | OTP input | Verification codes |
| `MifosSearchTextField` | Search input | Search bars |
| `MifosCard` | Card container | Content cards |
| `MifosBottomSheet` | Bottom sheet | Modal content |
| `MifosAlertDialog` | Alert dialog | Confirmations |
| `MifosBasicDialog` | Basic dialog | Simple messages |
| `MifosLoadingDialog` | Loading dialog | Blocking loader |
| `MifosTab` | Tab item | Tab navigation |
| `MifosTabPager` | Tab pager | Swipeable tabs |
| `MifosDropDownMenu` | Dropdown menu | Selection menu |
| `MifosRadioButton` | Radio button | Single selection |
| `MifosNavigation` | Navigation | Nav components |
---
### Business Components (core/ui)
**Prefix: `Mifos*` or descriptive name**
#### Cards
| Component | Purpose | Usage |
|-----------|---------|-------|
| `MifosAccountCard` | Account display | Account list items |
| `MifosDetailsCard` | Detail display | Information cards |
| `MifosDashboardCard` | Dashboard item | Home dashboard |
| `MifosActionCard` | Action card | Clickable actions |
| `MifosItemCard` | Generic item | List items |
| `MifosLabelValueCard` | Key-value | Detail rows |
| `MifosPoweredCard` | Footer card | "Powered by" |
| `MifosTitleSearchCard` | Title + search | Searchable headers |
#### Lists & Items
| Component | Purpose | Usage |
|-----------|---------|-------|
| `BeneficiaryCard` | Beneficiary item | Beneficiary list |
| `BeneficiariesListing` | Beneficiary list | Full list view |
| `TransactionScreenItem` | Transaction item | Transaction list |
| `FaqItemHolder` | FAQ item | Expandable FAQ |
| `AboutUsItemCard` | About item | About section |
| `MonitorListItemWithIcon` | Icon list item | Settings list |
#### States
| Component | Purpose | Usage |
|-----------|---------|-------|
| `MifosErrorComponent` | Error state | Error display |
| `EmptyDataView` | Empty state | No data |
| `NoInternet` | Network error | Offline state |
| `MifosProgressIndicator` | Loading spinner | Inline loading |
| `MifosStatusComponent` | Status badge | Status display |
| `MifosSuccessDialog` | Success dialog | Confirmation |
#### Forms
| Component | Purpose | Usage |
|-----------|---------|-------|
| `MifosDropDownTextField` | Dropdown field | Form dropdowns |
| `MifosOutlineDropDown` | Outlined dropdown | Outlined variant |
| `MifosDropDownPayFromComponent` | Pay from selector | Transfer forms |
| `MifosCheckBox` | Checkbox | Multi-select |
| `MFStepProcess` | Step indicator | Multi-step forms |
| `FilterTopSection` | Filter header | List filters |
#### User/Profile
| Component | Purpose | Usage |
|-----------|---------|-------|
| `MifosUserImage` | User avatar | Profile images |
| `MifosTextUserImage` | Text avatar | Initials avatar |
| `UserProfileField` | Profile field | Profile display |
| `MifosHiddenTextRow` | Hidden text | Sensitive data |
#### Other
| Component | Purpose | Usage |
|-----------|---------|-------|
| `MifosRoundIcon` | Round icon button | FAB-like |
| `MifosLinkText` | Link text | Clickable links |
| `MifosTextButtonWithTopDrawable` | Text button + icon | Icon buttons |
| `MifosMobileIcon` | App icon | Branding |
| `MifosRadioButtonAlertDialog` | Radio dialog | Selection dialog |
| `MifosAlertDialog` | Alert dialog | Confirmations |
| `MifosTexts` | Text styles | Styled text |
---
## Dynamic Discovery
### When to Use
Use dynamic discovery when:
1. Component not found in static registry above
2. Searching for recently added components
3. Unsure if component exists
### Discovery Commands
```bash
# Foundation components (Kpt*)
ls core-base/designsystem/src/commonMain/kotlin/**/component/
ls core-base/designsystem/src/commonMain/kotlin/**/layout/
# Design system components (Mifos* in designsystem)
ls core/designsystem/src/commonMain/kotlin/**/component/
# Business components (core/ui)
ls core/ui/src/commonMain/kotlin/**/component/
```
### Search by Type
```bash
# Find all Button components
grep -r "@Composable" core/ core-base/ | grep -i "button"
# Find all Card components
grep -r "@Composable" core/ core-base/ | grep -i "card"
# Find all Dialog components
grep -r "@Composable" core/ core-base/ | grep -i "dialog"
# Find all TextField/Input components
grep -r "@Composable" core/ core-base/ | grep -iE "(textfield|input|field)"
# Find loading/progress components
grep -r "@Composable" core/ core-base/ | grep -iE "(loading|progress|shimmer)"
# Find error/empty state components
grep -r "@Composable" core/ core-base/ | grep -iE "(error|empty|nodata)"
```
### Claude Glob Patterns
```
core-base/designsystem/**/component/*.kt
core-base/designsystem/**/layout/*.kt
core/designsystem/**/component/*.kt
core/ui/**/component/*.kt
```
---
## Naming Conventions
### Prefix Rules
| Prefix | Location | Purpose |
|--------|----------|---------|
| `Kpt*` | core-base/designsystem | Foundation/Theme |
| `Mifos*` | core/designsystem | UI primitives |
| `Mifos*` | core/ui | Business components |
| `[Feature]*` | feature/[name]/components | Feature-shared |
| `[Screen]*` | feature/[name]/[screen]/components | Screen-specific |
### Component Type by Name Pattern
| Pattern | Type | Look In |
|---------|------|---------|
| `*Button` | Action | core/designsystem |
| `*TextField`, `*Field` | Input | core/designsystem |
| `*Dialog`, `*Sheet` | Modal | core/designsystem |
| `*Card` | Container | core/ui |
| `*Item` | List item | core/ui |
| `*Component`, `*View` | Composite | core/ui |
| `*Indicator` | Feedback | core/ui |
| `*Grid`, `*Row`, `*Column` | Layout | core-base |
| `*Scaffold`, `*Layout` | Structure | core-base |
---
## Auto-Update Rules
### When to Update This File
| Scenario | Action |
|----------|--------|
| Found in static registry | No update needed |
| Found via dynamic search | ADD to static registry |
| Created new component in core/ | ADD to static registry |
| Created feature component | No update (not in registry) |
### How to Update
When you find a component dynamically that's not in the static registry:
1. Identify the correct table (Foundation/Design System/Business)
2. Add a new row with: Component | Purpose | Usage
3. Keep tables alphabetically sorted within categories
**Example:**
```markdown
| `NewMifosComponent` | Brief purpose | When to use |
```
### What NOT to Update
- Feature-specific components (`feature/*/components/`)
- Screen-specific components (`feature/*/[screen]/components/`)
- Temporary or experimental components
---
## Component Placement
### Decision Tree
```
Creating a new component?
├── Is it a theme/layout primitive?
│ └── YES → core-base/designsystem (Kpt*)
├── Is it a UI primitive (Button, TextField)?
│ └── YES → core/designsystem (Mifos*)
├── Used in 2+ features?
│ └── YES → core/ui (Mifos*)
├── Used across screens in same feature?
│ └── YES → feature/[name]/components/
└── Used only in one screen?
└── YES → feature/[name]/[screen]/components/
```
### After Creating in core/
If you create a new component in `core/` or `core-base/`:
1. **ADD it to the static registry above**
2. Follow the naming convention
3. Include Purpose and Usage columns
---
## Quick Reference
### I need a...
| Need | Check Static Table | If Not Found |
|------|-------------------|--------------|
| Button | Design System Components | `grep -i button core/` |
| Card | Business Components → Cards | `grep -i card core/` |
| List item | Business Components → Lists | `grep -i item core/` |
| Loading | Foundation Components | Already exists: `KptShimmerLoadingBox` |
| Error | Business Components → States | Already exists: `MifosErrorComponent` |
| Empty | Business Components → States | Already exists: `EmptyDataView` |
| Dialog | Design System Components | `grep -i dialog core/` |
| Layout | Foundation Layouts | `grep -i layout core-base/` |
---
## Related Files
- Feature Layer Guide: `feature-layer/LAYER_GUIDE.md`
- Compose Patterns: `feature-layer/instructions/COMPOSE.md`
- Design Spec Patterns: `design-spec-layer/_shared/PATTERNS.md`
---
## Changelog
| Date | Change |
|------|--------|
| 2025-01-05 | Created with hybrid static + dynamic approach |

View File

@ -1,283 +0,0 @@
# Design Tokens Index - O(1) Lookup
> **8 features** with tokens | **2 formats** (Google Stitch, MD3) | **Last Updated**: 2026-01-05
---
## Quick Lookup
| # | Feature | Has Tokens | Format | Colors | Typography | Components | Animations |
|:-:|---------|:----------:|--------|:------:|:----------:|:----------:|:----------:|
| 1 | auth | ✅ | google-stitch | ✅ | ✅ | ✅ | ✅ |
| 2 | dashboard | ✅ | md3 | ✅ | ✅ | ✅ | ❌ |
| 3 | settings | ✅ | md3 | ✅ | ✅ | ❌ | ❌ |
| 4 | guarantor | ✅ | md3 | ✅ | ✅ | ❌ | ❌ |
| 5 | qr | ✅ | md3 | ✅ | ✅ | ❌ | ❌ |
| 6 | passcode | ✅ | md3 | ✅ | ✅ | ❌ | ❌ |
| 7 | location | ✅ | md3 | ✅ | ✅ | ❌ | ❌ |
| 8 | client-charge | ✅ | md3 | ✅ | ✅ | ❌ | ❌ |
| 9 | accounts | ❌ | - | - | - | - | - |
| 10 | beneficiary | ❌ | - | - | - | - | - |
| 11 | home | ❌ | - | - | - | - | - |
| 12 | loan-account | ❌ | - | - | - | - | - |
| 13 | notification | ❌ | - | - | - | - | - |
| 14 | recent-transaction | ❌ | - | - | - | - | - |
| 15 | savings-account | ❌ | - | - | - | - | - |
| 16 | share-account | ❌ | - | - | - | - | - |
| 17 | transfer | ❌ | - | - | - | - | - |
---
## Token Formats
### Google Stitch Format (v2.0)
```json
{
"feature": "auth",
"generated": "2026-01-03",
"tool": "google-stitch",
"version": "2.0",
"tokens": {
"colors": {
"primary": { "gradient": {...}, "solid": "#667EEA" },
"surface": { "light": "#FFFFFF", "dark": "#0D1117" },
"text": { "primary": {...}, "secondary": {...} },
"semantic": { "success": "#00D09C", "error": "#FF4757" }
},
"typography": { "fontFamily": "Inter", "display": {...}, "headline": {...} },
"spacing": { "xs": "4dp", "sm": "8dp", "md": "12dp", "lg": "16dp" },
"radius": { "sm": "8dp", "md": "12dp", "lg": "16dp" },
"shadow": { "button": {...}, "card": {...} }
},
"screens": [...],
"components": [...],
"animations": {...}
}
```
### MD3 Format (Standard)
```json
{
"feature": "Dashboard",
"generated": "2025-12-28",
"tokens": {
"colors": { "primary": "#6750A4", "surface": "#FFFBFE", ... },
"typography": { "displayLarge": {...}, "bodyMedium": {...} },
"spacing": { "xs": 4, "sm": 8, "md": 16 },
"radius": { "sm": 8, "md": 12, "lg": 16 }
},
"components": [...],
"screens": [...]
}
```
---
## O(1) Path Pattern
```
design-spec-layer/features/[feature]/mockups/design-tokens.json
```
---
## Token → DesignToken Mapping
| Token JSON | Compose DesignToken | Type |
|------------|---------------------|------|
| `tokens.spacing.xs` | `DesignToken.spacing.extraSmall` | `Dp` |
| `tokens.spacing.sm` | `DesignToken.spacing.small` | `Dp` |
| `tokens.spacing.md` | `DesignToken.spacing.medium` | `Dp` |
| `tokens.spacing.lg` | `DesignToken.spacing.large` | `Dp` |
| `tokens.radius.sm` | `DesignToken.shapes.small` | `Shape` |
| `tokens.radius.md` | `DesignToken.shapes.medium` | `Shape` |
| `tokens.radius.lg` | `DesignToken.shapes.large` | `Shape` |
| `tokens.colors.primary` | `MaterialTheme.colorScheme.primary` | `Color` |
| `tokens.colors.surface` | `MaterialTheme.colorScheme.surface` | `Color` |
---
## Gradient Support
Features with gradients (Google Stitch format):
| Feature | Gradient Type | Colors | Usage |
|---------|---------------|--------|-------|
| auth | primary | `#667EEA → #764BA2` | Buttons, headers |
| auth | secondary | `#11998E → #38EF7D` | Success states |
### Compose Gradient Code
```kotlin
// From design-tokens.json:
// "gradient": { "start": "#667EEA", "end": "#764BA2", "angle": 45 }
val AuthGradient = Brush.linearGradient(
colors = listOf(
Color(0xFF667EEA),
Color(0xFF764BA2)
),
start = Offset(0f, 0f),
end = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
)
// Usage in Button:
Button(
onClick = { },
colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent),
modifier = Modifier.background(AuthGradient, shape = DesignToken.shapes.large)
) {
Text("Login")
}
```
---
## Component Specs
Features with component specifications:
| Feature | Components | Details |
|---------|:----------:|---------|
| auth | 5 | primary-button, text-input, otp-input, auth-card, trust-badge |
| dashboard | 7 | NetWorthCard, QuickActions, AccountCard, TransactionItem, BottomNav, TopBar, SectionHeader |
### Component Spec Example
```json
{
"id": "primary-button",
"name": "Primary Button",
"specs": {
"height": "56dp",
"radius": "16dp",
"background": "gradient",
"textSize": "16sp",
"textWeight": "600",
"textColor": "#FFFFFF",
"shadow": "button"
}
}
```
### Generated Compose Code
```kotlin
@Composable
fun AuthPrimaryButton(
text: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Button(
onClick = onClick,
modifier = modifier
.height(56.dp)
.background(
brush = AuthGradient,
shape = RoundedCornerShape(16.dp)
),
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent
),
shape = RoundedCornerShape(16.dp),
) {
Text(
text = text,
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
color = Color.White,
)
}
}
```
---
## Animation Specs
Features with animation specifications:
| Feature | Animations | Details |
|---------|:----------:|---------|
| auth | 5 | pageTransition, buttonPress, inputFocus, successCelebration, errorShake |
### Animation Spec Example
```json
"animations": {
"buttonPress": {
"scale": "0.98",
"duration": "100ms"
},
"errorShake": {
"translateX": "[-10, 10, -5, 5, 0]",
"duration": "300ms"
}
}
```
---
## Usage in /feature Command
### Phase 0: O(1) Context Loading
```kotlin
// Check if design tokens exist
val tokensPath = "design-spec-layer/features/$feature/mockups/design-tokens.json"
val hasTokens = checkInIndex("DESIGN_TOKENS_INDEX.md", feature)
val tokenFormat = getTokenFormat(feature) // "google-stitch" | "md3" | null
```
### Phase 3: Apply Design Tokens
```
IF hasTokens THEN
1. Read design-tokens.json
2. Extract colors → Generate feature-specific colors if custom
3. Extract gradients → Generate Brush definitions
4. Extract component specs → Apply to generated components
5. Extract animations → Add animation modifiers
6. Map spacing/radius → Use DesignToken equivalents
ELSE
Use default DesignToken values
END
```
---
## Auto-Update Rules
| Scenario | Action |
|----------|--------|
| New tokens generated | Add row to Quick Lookup table |
| `/design mockup` completes | Update Has Tokens column |
| Token format changes | Update Format column |
| Components added | Update Components column |
---
## Related Files
- [FEATURES_INDEX.md](./FEATURES_INDEX.md) - All features
- [MOCKUPS_INDEX.md](./MOCKUPS_INDEX.md) - Mockup status
- `core/designsystem/theme/DesignToken.kt` - Compose design tokens
- `core/designsystem/theme/Color.kt` - Color definitions
---
## Commands
```bash
# Check token status
/gap-analysis design tokens
# Generate tokens for feature
/design [feature] mockup
# Feature with token integration
/feature [feature] # Auto-applies tokens if available
```

View File

@ -1,116 +0,0 @@
# Features Index - O(1) Lookup
> **18 features** | All have SPEC + API + STATUS
---
## Quick Lookup
| # | Feature | Dir | SPEC | API | STATUS | Mockups |
|:-:|---------|-----|:----:|:---:|:------:|:-------:|
| 1 | accounts | features/accounts/ | ✅ | ✅ | ✅ | ⚠️ |
| 2 | auth | features/auth/ | ✅ | ✅ | ✅ | ✅ |
| 3 | beneficiary | features/beneficiary/ | ✅ | ✅ | ✅ | ⚠️ |
| 4 | client-charge | features/client-charge/ | ✅ | ✅ | ✅ | ⚠️ |
| 5 | dashboard | features/dashboard/ | ✅ | ✅ | ✅ | ⚠️ |
| 6 | guarantor | features/guarantor/ | ✅ | ✅ | ✅ | ⚠️ |
| 7 | home | features/home/ | ✅ | ✅ | ✅ | ⚠️ |
| 8 | loan-account | features/loan-account/ | ✅ | ✅ | ✅ | ⚠️ |
| 9 | location | features/location/ | ✅ | ✅ | ✅ | ⚠️ |
| 10 | notification | features/notification/ | ✅ | ✅ | ✅ | ⚠️ |
| 11 | passcode | features/passcode/ | ✅ | ✅ | ✅ | ⚠️ |
| 12 | qr | features/qr/ | ✅ | ✅ | ✅ | ⚠️ |
| 13 | recent-transaction | features/recent-transaction/ | ✅ | ✅ | ✅ | ⚠️ |
| 14 | savings-account | features/savings-account/ | ✅ | ✅ | ✅ | ⚠️ |
| 15 | settings | features/settings/ | ✅ | ✅ | ✅ | ⚠️ |
| 16 | share-account | features/share-account/ | ✅ | ✅ | ✅ | ⚠️ |
| 17 | transfer | features/transfer/ | ✅ | ✅ | ✅ | ⚠️ |
**Legend**: ✅ Complete | ⚠️ Partial | ❌ Missing
---
## O(1) File Access
| Need | Path |
|------|------|
| Specification | `features/[name]/SPEC.md` |
| API Endpoints | `features/[name]/API.md` |
| Feature Status | `features/[name]/STATUS.md` |
| Mockups | `features/[name]/mockups/` |
| Design Tokens | `features/[name]/mockups/design-tokens.json` |
---
## Feature Categories
### Authentication & Security (3)
| Feature | Purpose |
|---------|---------|
| auth | Login, Registration, Password recovery |
| passcode | Biometric/PIN security |
| settings | Password change, security settings |
### Account Management (4)
| Feature | Purpose |
|---------|---------|
| accounts | Account overview, all account types |
| savings-account | Savings account details, operations |
| loan-account | Loan details, repayment schedule |
| share-account | Share account details |
### Transactions (3)
| Feature | Purpose |
|---------|---------|
| beneficiary | Third-party transfer beneficiaries |
| transfer | Fund transfers (self & TPT) |
| recent-transaction | Transaction history |
### Information & Utilities (5)
| Feature | Purpose |
|---------|---------|
| home | Dashboard, quick actions |
| notification | Push notifications |
| qr | QR code generation/scanning |
| location | Branch locator |
| client-charge | Client charges/fees |
### Supporting Features (2)
| Feature | Purpose |
|---------|---------|
| guarantor | Loan guarantor management |
| dashboard | Main navigation hub |
---
## Design Progress Summary
| Status | Count | Features |
|--------|:-----:|----------|
| Complete (all mockups) | 1 | auth |
| Partial (some mockups) | 16 | All others |
| Not Started | 0 | - |
---
## Related Files
- [MOCKUPS_INDEX.md](MOCKUPS_INDEX.md) - Mockup completion status
- [STATUS.md](STATUS.md) - Layer-wide status tracker
- [TOOL_CONFIG.md](TOOL_CONFIG.md) - Design tool configuration
---
## Auto-Update Rules
| Scenario | Action |
|----------|--------|
| New feature added | Add row to Quick Lookup |
| SPEC.md created | Update SPEC column to ✅ |
| API.md created | Update API column to ✅ |
| Mockups complete | Update Mockups column to ✅ |

View File

@ -1,152 +0,0 @@
# Mockups Index - O(1) Lookup
> **Figma**: 7/18 | **Stitch**: 11/18 | **Tokens**: 8/18
---
## Status Matrix
| Feature | FIGMA_LINKS | PROMPTS_FIGMA | PROMPTS_STITCH | design-tokens |
|---------|:-----------:|:-------------:|:--------------:|:-------------:|
| accounts | ❌ | ✅ | ✅ | ❌ |
| auth | ✅ | ✅ | ✅ | ✅ |
| beneficiary | ❌ | ✅ | ✅ | ❌ |
| client-charge | ✅ | ❌ | ❌ | ✅ |
| dashboard | ❌ | ✅ | ✅ | ✅ |
| guarantor | ✅ | ❌ | ❌ | ✅ |
| home | ❌ | ✅ | ✅ | ❌ |
| loan-account | ❌ | ✅ | ✅ | ❌ |
| location | ✅ | ❌ | ❌ | ✅ |
| notification | ❌ | ✅ | ✅ | ❌ |
| passcode | ✅ | ❌ | ❌ | ✅ |
| qr | ✅ | ❌ | ❌ | ✅ |
| recent-transaction | ❌ | ✅ | ✅ | ❌ |
| savings-account | ❌ | ✅ | ✅ | ❌ |
| settings | ✅ | ❌ | ❌ | ✅ |
| share-account | ❌ | ✅ | ✅ | ❌ |
| transfer | ❌ | ✅ | ✅ | ❌ |
**Legend**: ✅ Exists | ❌ Missing
---
## O(1) File Access
| Need | Path |
|------|------|
| Figma Links | `features/[name]/mockups/FIGMA_LINKS.md` |
| Figma Prompts | `features/[name]/mockups/PROMPTS_FIGMA.md` |
| Stitch Prompts | `features/[name]/mockups/PROMPTS_STITCH.md` |
| Design Tokens | `features/[name]/mockups/design-tokens.json` |
---
## Completion Summary
### Complete (All 4 Files)
| Feature | Status |
|---------|--------|
| auth | ✅ All mockup files present |
### Has Figma Links + Tokens (Need Prompts)
| Feature | Has | Needs |
|---------|-----|-------|
| client-charge | FIGMA_LINKS, design-tokens | PROMPTS_FIGMA, PROMPTS_STITCH |
| guarantor | FIGMA_LINKS, design-tokens | PROMPTS_FIGMA, PROMPTS_STITCH |
| location | FIGMA_LINKS, design-tokens | PROMPTS_FIGMA, PROMPTS_STITCH |
| passcode | FIGMA_LINKS, design-tokens | PROMPTS_FIGMA, PROMPTS_STITCH |
| qr | FIGMA_LINKS, design-tokens | PROMPTS_FIGMA, PROMPTS_STITCH |
| settings | FIGMA_LINKS, design-tokens | PROMPTS_FIGMA, PROMPTS_STITCH |
### Has Prompts (Need Figma Links + Tokens)
| Feature | Has | Needs |
|---------|-----|-------|
| accounts | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
| beneficiary | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
| home | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
| loan-account | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
| notification | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
| recent-transaction | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
| savings-account | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
| share-account | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
| transfer | PROMPTS_FIGMA, PROMPTS_STITCH | FIGMA_LINKS, design-tokens |
### Has Prompts + Tokens (Need Figma Links)
| Feature | Has | Needs |
|---------|-----|-------|
| dashboard | PROMPTS_FIGMA, PROMPTS_STITCH, design-tokens | FIGMA_LINKS |
---
## Gaps by File Type
### Need FIGMA_LINKS.md (11 features)
```
accounts, beneficiary, dashboard, home, loan-account,
notification, recent-transaction, savings-account,
share-account, transfer
```
### Need design-tokens.json (9 features)
```
accounts, beneficiary, home, loan-account, notification,
recent-transaction, savings-account, share-account, transfer
```
### Need PROMPTS_FIGMA.md (6 features)
```
client-charge, guarantor, location, passcode, qr, settings
```
### Need PROMPTS_STITCH.md (6 features)
```
client-charge, guarantor, location, passcode, qr, settings
```
---
## Design Tool Workflows
### Figma-First Workflow
```
1. Create in Figma
2. Add link to FIGMA_LINKS.md
3. Export design-tokens.json
```
### AI-Generation Workflow (Google Stitch)
```
1. Write PROMPTS_STITCH.md
2. Generate mockups
3. Export to Figma
4. Update FIGMA_LINKS.md
```
---
## Related Files
- [FEATURES_INDEX.md](FEATURES_INDEX.md) - Feature overview
- [TOOL_CONFIG.md](TOOL_CONFIG.md) - Tool configuration
- [STATUS.md](STATUS.md) - Layer status
---
## Auto-Update Rules
| Scenario | Action |
|----------|--------|
| Figma link added | Update FIGMA_LINKS column to ✅ |
| Prompts created | Update respective column to ✅ |
| Tokens exported | Update design-tokens column to ✅ |
| All 4 files done | Move to "Complete" section |

View File

@ -1,232 +0,0 @@
# STATUS.md - Single Source of Truth for Implementation Status
> **Purpose**: ONE file to check and update all implementation status
> **Rule**: Update THIS file after any implementation work
> **Last Verified**: 2025-12-28
---
## Quick Overview
| Phase | Features | Done | In Progress | Planned |
|-------|----------|------|-------------|---------|
| Core MVP | 6 | 6 | 0 | 0 |
| Account Management | 5 | 5 | 0 | 0 |
| Utilities | 5 | 5 | 0 | 0 |
| New Features | 1 | 0 | 0 | 1 |
**Next Priority**: Dashboard - Unified Account Management
---
## Phase 1: Core MVP
| Feature | Status | Client | Feature | Gaps |
|---------|--------|--------|---------|------|
| Auth (Login/Register) | ✅ Done | ✅ | ✅ | 0 |
| Home Dashboard | ✅ Done | ✅ | ✅ | 0 |
| Accounts Overview | ✅ Done | ✅ | ✅ | 0 |
| Recent Transactions | ✅ Done | ✅ | ✅ | 0 |
| Notifications | ✅ Done | ✅ | ✅ | 0 |
| Settings | ✅ Done | ✅ | ✅ | 0 |
---
## Phase 2: Account Management
| Feature | Status | Client | Feature | Gaps |
|---------|--------|--------|---------|------|
| Savings Account | ✅ Done | ✅ | ✅ | 0 |
| Loan Account | ✅ Done | ✅ | ✅ | 0 |
| Share Account | ✅ Done | ✅ | ✅ | 0 |
| Beneficiary | ✅ Done | ✅ | ✅ | 0 |
| Transfer | ✅ Done | ✅ | ✅ | 0 |
---
## Phase 3: Utilities
| Feature | Status | Client | Feature | Gaps |
|---------|--------|--------|---------|------|
| Passcode | ✅ Done | - | ✅ | 0 |
| QR Code | ✅ Done | - | ✅ | 0 |
| Location | ✅ Done | - | ✅ | 0 |
| Guarantor | ✅ Done | ✅ | ✅ | 0 |
| Client Charges | ✅ Done | ✅ | ✅ | 0 |
---
## Phase 4: New Features
| Feature | Status | Client | Feature | Gaps |
|---------|--------|--------|---------|------|
| Dashboard (Unified) | 📋 Planned | ✅ | 📋 | SPEC/API complete |
---
## Status Legend
| Status | Meaning |
|--------|---------|
| ✅ Done | Feature complete, all working |
| ⚠️ Needs Update | Has gaps, spec changed, or incomplete |
| 🔄 In Progress | Currently being implemented |
| 📋 Planned | Spec exists, not started |
| 🆕 Not Started | No work done |
---
## Layer Checklist Template
When implementing a feature, track layers here:
```
Feature: [Name]
- [ ] SPEC.md created
- [ ] API.md created
- [ ] Network: Service created
- [ ] Data: Repository created
- [ ] Feature: ViewModel + Screen
- [ ] Navigation: Route registered
- [ ] DI: Modules registered
- [ ] STATUS.md updated
```
---
## Feature-to-Module Mapping
| Feature | Module Path | Main Files |
|---------|-------------|------------|
| Auth | `feature:auth` | AuthViewModel, LoginScreen, RegistrationScreen |
| Home | `feature:home` | HomeViewModel, HomeScreen |
| Accounts | `feature:accounts` | AccountsViewModel, AccountsScreen |
| Savings | `feature:savings-account` | SavingsAccountViewModel, SavingsAccountScreen |
| Loan | `feature:loan-account` | LoanAccountViewModel, LoanAccountScreen |
| Share | `feature:share-account` | ShareAccountViewModel, ShareAccountScreen |
| Beneficiary | `feature:beneficiary` | BeneficiaryViewModel, BeneficiaryScreen |
| Transfer | `feature:transfer-process` | TransferViewModel, TransferScreen |
| Transactions | `feature:recent-transaction` | RecentTransactionViewModel |
| Notifications | `feature:notification` | NotificationViewModel |
| Settings | `feature:settings` | SettingsViewModel, SettingsScreen |
| Passcode | `feature:passcode` | PasscodeViewModel |
| QR Code | `feature:qr` | QRCodeViewModel |
| Location | `feature:location` | LocationScreen |
| Guarantor | `feature:guarantor` | GuarantorViewModel |
| Charges | `feature:client-charge` | ClientChargeViewModel |
| Dashboard | `feature:dashboard` | DashboardViewModel, DashboardScreen |
---
## Detailed Feature Breakdown
### Auth Feature
- **Screens**: LoginScreen, RegistrationScreen, OtpAuthenticationScreen, RecoverPasswordScreen, SetPasswordScreen, UploadIdScreen
- **ViewModels**: LoginViewModel, RegistrationViewModel, OtpAuthenticationViewModel, RecoverPasswordViewModel, SetPasswordViewModel, UploadIdViewmodel
- **APIs**: /authentication, /registration, /registration/user
### Home Feature
- **Screens**: HomeScreen
- **ViewModels**: HomeViewModel
- **APIs**: /clients/{id}, /clients/{id}/accounts, /clients/{id}/images
- **Components**: 10 ServiceItems, BottomSheetContent, MifosDashboardCard
### Accounts Feature
- **Screens**: AccountsScreen, TransactionScreen
- **ViewModels**: AccountsViewModel, TransactionViewModel
- **APIs**: /clients/{id}/accounts, /savingsaccounts/{id}, /loans/{id}
- **Filters**: Status filters, Type filters
### Savings Account Feature
- **Screens**: SavingsAccountScreen, SavingsAccountDetailsScreen, AccountWithdrawScreen, AccountUpdateScreen
- **ViewModels**: SavingsAccountViewmodel, SavingsAccountDetailsViewModel, AccountWithdrawViewModel, AccountUpdateViewModel
- **APIs**: /savingsaccounts/{id}, /savingsaccounts/template, /accounttransfers
### Loan Account Feature
- **Screens**: LoanAccountScreen, LoanAccountDetailsScreen, RepaymentScheduleScreen, AccountSummaryScreen
- **ViewModels**: LoanAccountsViewmodel, LoanAccountDetailsViewModel, RepaymentScheduleViewModel, LoanAccountSummaryViewModel
- **APIs**: /loans/{id}, /loans/{id}?associations=repaymentSchedule
### Beneficiary Feature
- **Screens**: BeneficiaryListScreen, BeneficiaryApplicationScreen, BeneficiaryDetailScreen, BeneficiaryApplicationConfirmationScreen
- **ViewModels**: BeneficiaryListViewModel, BeneficiaryApplicationViewModel, BeneficiaryDetailViewModel, BeneficiaryApplicationConfirmationViewModel
- **APIs**: /beneficiaries/tpt, /beneficiaries/tpt/template
### Transfer Feature
- **Screens**: MakeTransferScreen, TransferProcessScreen
- **ViewModels**: MakeTransferViewModel, TransferProcessViewModel
- **APIs**: /accounttransfers, /accounttransfers/template, /accounttransfers?type=tpt
### Recent Transaction Feature
- **Screens**: RecentTransactionScreen
- **ViewModels**: RecentTransactionViewModel
- **APIs**: /clients/{id}/transactions
### Notification Feature
- **Screens**: NotificationScreen
- **ViewModels**: NotificationViewModel
- **APIs**: /device/registration/client/{id}
### Settings Feature
- **Screens**: SettingsScreen, ThemeScreen, LanguageScreen, ChangePasswordScreen, UpdatePasscodeScreen, FaqScreen, HelpScreen, AboutScreen, AppInfoScreen
- **ViewModels**: SettingsViewModel, ChangeThemeViewModel, LanguageViewModel, ChangePasswordViewModel, UpdatePasscodeViewModel, FaqViewModel
- **APIs**: None (local preferences)
### Share Account Feature
- **Screens**: ShareAccountScreen
- **ViewModels**: ShareAccountsViewmodel
- **APIs**: /products/share, /shareaccounts
### Passcode Feature
- **Screens**: PasscodeScreen, VerifyPasscodeScreen
- **ViewModels**: PasscodeViewModel
- **APIs**: None (local storage)
### QR Feature
- **Screens**: QrCodeReaderScreen, QrCodeDisplayScreen, QrCodeImportScreen
- **ViewModels**: QrCodeReaderViewModel, QrCodeDisplayViewModel, QrCodeImportViewModel
- **APIs**: None (local processing)
### Location Feature
- **Screens**: LocationScreen
- **ViewModels**: None
- **APIs**: None (static content)
### Guarantor Feature
- **Screens**: GuarantorListScreen, GuarantorDetailScreen, AddGuarantorScreen
- **ViewModels**: GuarantorListViewModel, GuarantorDetailViewModel, AddGuarantorViewModel
- **APIs**: /loans/{id}/guarantors, /loans/{id}/guarantors/template
### Client Charge Feature
- **Screens**: ClientChargeScreen, ChargeDetailScreen
- **ViewModels**: ClientChargeViewModel, ChargeDetailsViewModel
- **APIs**: /clients/{id}/charges, /loans/{id}/charges, /savingsaccounts/{id}/charges
### Dashboard Feature (NEW)
- **Screens**: DashboardScreen
- **ViewModels**: DashboardViewModel
- **Components**: NetWorthCard, AccountCard, TransactionItem, QuickActionBar
- **APIs**: /clients/{id}, /clients/{id}/accounts, /clients/{id}/images, /clients/{id}/transactions, /savingsaccounts/{id}, /loans/{id}, /beneficiaries/tpt, /accounttransfers/template, /accounttransfers
- **Design Docs**: [SPEC.md](features/dashboard/SPEC.md), [API.md](features/dashboard/API.md), [STATUS.md](features/dashboard/STATUS.md)
---
## Recent Updates
| Date | Feature | Change |
|------|---------|--------|
| 2025-12-29 | All Features | Created comprehensive SPEC.md and API.md for all 16 features |
| 2025-12-28 | Mockup Layer | Created mockup-layer with Figma plugin and /mockup skill |
| 2025-12-28 | Dashboard | Production-level SPEC.md and API.md created |
| 2025-12-27 | All | Comprehensive design analysis and SPEC/API documentation |
| 2025-12-26 | All | Initial claude-product-cycle setup |
---
## How to Update This File
1. **After implementing code**: Check off layers in feature section
2. **After completing feature**: Change status from 🔄 to ✅
3. **After spec change**: Change status to ⚠️ and list gaps
4. **Add recent update**: Add row to Recent Updates table
5. **IMPORTANT**: Run `/projectstatus` periodically to verify accuracy

View File

@ -1,125 +0,0 @@
# Design Layer - Testing Status
> Testing specifications for design layer validation
---
## Overview
The design layer defines **what** should be tested. Each feature specification includes acceptance criteria that translate directly to test cases.
---
## Testing Scope
| Component | Test Type | Purpose |
|-----------|-----------|---------|
| SPEC.md | Contract Tests | Verify implementation matches specification |
| API.md | API Contract Tests | Verify API usage matches documentation |
| Mockups | Screenshot Tests | Visual regression testing |
| design-tokens.json | Theme Tests | Verify design tokens applied correctly |
---
## Per-Feature Testing Requirements
### Test Coverage Matrix
| # | Feature | Contract | API | Screenshot | Status |
|:-:|---------|:--------:|:---:|:----------:|:------:|
| 1 | auth | ⬜ | ⬜ | ⬜ | Not Started |
| 2 | home | ⬜ | ⬜ | ⬜ | Not Started |
| 3 | accounts | ⬜ | ⬜ | ⬜ | Not Started |
| 4 | savings-account | ⬜ | ⬜ | ⬜ | Not Started |
| 5 | loan-account | ⬜ | ⬜ | ⬜ | Not Started |
| 6 | share-account | ⬜ | ⬜ | ⬜ | Not Started |
| 7 | beneficiary | ⬜ | ⬜ | ⬜ | Not Started |
| 8 | transfer | ⬜ | ⬜ | ⬜ | Not Started |
| 9 | recent-transaction | ⬜ | ⬜ | ⬜ | Not Started |
| 10 | notification | ⬜ | ⬜ | ⬜ | Not Started |
| 11 | settings | ⬜ | ⬜ | ⬜ | Not Started |
| 12 | passcode | ⬜ | - | ⬜ | Not Started |
| 13 | guarantor | ⬜ | ⬜ | ⬜ | Not Started |
| 14 | qr | ⬜ | - | ⬜ | Not Started |
| 15 | location | ⬜ | - | ⬜ | Not Started |
| 16 | client-charge | ⬜ | ⬜ | ⬜ | Not Started |
| 17 | dashboard | ⬜ | ⬜ | ⬜ | Not Started |
**Legend**: ✅ Complete | ⬜ Not Started | - N/A
---
## Testing Specification Template
Each feature's SPEC.md should include a `## Test Scenarios` section:
```markdown
## Test Scenarios
### Loading State
- [ ] Shows loading indicator when data is being fetched
- [ ] Disables user interaction during loading
### Success State
- [ ] Displays all required data fields
- [ ] Data matches API response
- [ ] Navigation works correctly
### Error State
- [ ] Shows error message for network failures
- [ ] Retry button is visible and functional
- [ ] Error message is user-friendly
### Empty State
- [ ] Shows appropriate message when no data
- [ ] Optional: Call-to-action for creating data
### Validation
- [ ] Required fields show error when empty
- [ ] Format validation (email, phone, etc.)
- [ ] Business rules validation
```
---
## Screenshot Test Baseline
For mockups to become screenshot test baselines:
| Step | Action | Output |
|:----:|--------|--------|
| 1 | Generate mockups (Google Stitch/Figma) | PNG/SVG files |
| 2 | Export to `mockups/` folder | Light + Dark variants |
| 3 | Configure Roborazzi | Golden images |
| 4 | Run screenshot tests | Compare against baseline |
---
## Implementation Priority
| Priority | Features | Reason |
|:--------:|----------|--------|
| P0 | auth, home | Core user flow |
| P1 | accounts, transfer, beneficiary | Primary functionality |
| P2 | loan-account, savings-account | Account management |
| P3 | Others | Supporting features |
---
## Commands
```bash
# Validate feature spec has test scenarios
/verify [feature] testing
# Generate test cases from spec
/gap-planning [feature] testing
```
---
## Related Files
- [FEATURES_INDEX.md](./FEATURES_INDEX.md) - Feature status
- [MOCKUPS_INDEX.md](./MOCKUPS_INDEX.md) - Mockup status
- Each feature's `SPEC.md` - Detailed specifications

View File

@ -1,190 +0,0 @@
# Design Tools Configuration
Configuration for AI design tools and MCP connections used in mockup generation.
---
## Selected AI Design Tool
**Current Tool**: Google Stitch
| Setting | Value |
|---------|-------|
| Primary Tool | `google-stitch` |
| Fallback Tool | `figma` |
| Prompt Format | `md3-detailed` |
### Available Tools
| ID | Tool | Website | MCP | Status |
|----|------|---------|:---:|:------:|
| `google-stitch` | Google Stitch | [stitch.withgoogle.com](https://stitch.withgoogle.com/) | ✅ | **Selected** |
| `figma` | Figma | [figma.com](https://www.figma.com/) | ✅ | Available |
| `uizard` | Uizard | [uizard.io](https://uizard.io/) | ❌ | Available |
| `visily` | Visily | [visily.ai](https://www.visily.ai/) | ❌ | Available |
---
## MCP Servers
### Google Stitch MCP
**Repository**: [github.com/StitchAI/stitch-ai-mcp](https://github.com/StitchAI/stitch-ai-mcp)
**Install**:
```bash
claude mcp add stitch-ai -- npx -y stitch-ai-mcp
```
**Features**:
- Generate UI designs from text prompts
- Material Design 3 native support
- Export to various formats
- Direct Figma integration
**Status**: Not Connected
---
### Figma MCP
**Documentation**: [Claude Code MCP Docs](https://github.com/anthropics/claude-code/tree/main/docs/mcp)
**Install**:
```bash
# Get your Figma token from: https://www.figma.com/developers/api#access-tokens
claude mcp add figma -- npx -y figma-mcp --token YOUR_FIGMA_TOKEN
```
**Features**:
- Read Figma files and components
- Extract design tokens
- Get component specifications
- Access design system
**Status**: Not Connected
---
## Prompt Formats
### MD3 Detailed (Google Stitch)
Best for Material Design 3 apps. Includes:
- Detailed component specifications
- Color tokens with gradients
- Typography scale
- Spacing and radius values
- Animation hints
### Figma Native
Best for Figma AI. Includes:
- Component structure
- Auto-layout hints
- Variant specifications
- Design system references
### Concise (Uizard/Visily)
Best for quick prototypes. Includes:
- Screen description
- Key components list
- Basic styling
---
## How to Change Tool
### Option 1: Edit this file
Change the "Current Tool" section above.
### Option 2: Select at runtime
When running `/design [feature] mockup`, you'll be prompted to select a tool.
### Option 3: Use command argument
```
/design auth mockup --tool=google-stitch
/design auth mockup --tool=figma
/design auth mockup --tool=uizard
```
---
## Workflow by Tool
### Google Stitch (Recommended)
```
1. /design [feature] mockup
2. Claude generates PROMPTS.md with Stitch format
3. If MCP connected: Claude sends to Stitch directly
If no MCP: Copy prompt to stitch.withgoogle.com
4. Generate design
5. Export to Figma
6. Update FIGMA_LINKS.md
```
### Figma + AI
```
1. /design [feature] mockup
2. Claude generates PROMPTS.md with Figma format
3. Open Figma, use AI feature
4. Paste prompt
5. Generate design
6. Update FIGMA_LINKS.md
```
### Uizard / Visily
```
1. /design [feature] mockup
2. Claude generates PROMPTS.md with concise format
3. Open tool website
4. Paste prompt
5. Generate design
6. Export to Figma
7. Update FIGMA_LINKS.md
```
---
## Check MCP Status
Run in terminal:
```bash
claude mcp list
```
Expected output (if configured):
```
MCP Servers:
stitch-ai ✓ connected
figma ✓ connected
```
---
## Troubleshooting
### MCP Not Connecting
1. Check Node.js is installed: `node --version`
2. Check npx works: `npx --version`
3. Try reinstalling: `claude mcp remove stitch-ai && claude mcp add stitch-ai -- npx -y stitch-ai-mcp`
### Figma Token Issues
1. Generate new token at: https://www.figma.com/developers/api#access-tokens
2. Ensure token has read access
3. Reinstall with new token
### Stitch Not Generating
1. Check you're signed into Google account
2. Verify prompt format is correct
3. Try simpler prompt first

View File

@ -1,212 +0,0 @@
# Fineract Self-Service API Quick Reference
> **Base URL**: `https://{server}/fineract-provider/api/v1/self/`
> **Authentication**: Basic Auth + Tenant Header
> **Last Updated**: 2025-12-26
---
## Authentication Headers
```
Authorization: Basic {base64(username:password)}
Fineract-Platform-TenantId: {tenant}
Content-Type: application/json
```
---
## API Endpoints
### Authentication
| Endpoint | Method | Description |
|----------|--------|-------------|
| `authentication` | POST | User login |
| `registration` | POST | User registration |
| `registration/user` | POST | Verify registration |
| `user` | GET | Get current user details |
| `user` | PUT | Update user details |
### Clients
| Endpoint | Method | Description |
|----------|--------|-------------|
| `clients` | GET | Get client list |
| `clients/{clientId}` | GET | Get client by ID |
| `clients/{clientId}/images` | GET | Get client image |
| `clients/{clientId}/accounts` | GET | Get client accounts |
| `clients/{clientId}/charges` | GET | Get client charges |
### Savings Accounts
| Endpoint | Method | Description |
|----------|--------|-------------|
| `savingsaccounts` | GET | Get savings accounts list |
| `savingsaccounts` | POST | Apply for savings account |
| `savingsaccounts/{accountId}` | GET | Get savings account details |
| `savingsaccounts/{accountId}` | PUT | Update savings account |
| `savingsaccounts/{accountId}?command=withdrawnByApplicant` | POST | Withdraw application |
| `savingsaccounts/template` | GET | Get savings account template |
| `savingsaccounts/{accountId}/transactions` | GET | Get transactions |
### Loan Accounts
| Endpoint | Method | Description |
|----------|--------|-------------|
| `loans` | GET | Get loan accounts list |
| `loans` | POST | Apply for loan |
| `loans/{loanId}` | GET | Get loan details |
| `loans/{loanId}` | PUT | Update loan |
| `loans/{loanId}?command=withdrawnByApplicant` | POST | Withdraw loan application |
| `loans/template` | GET | Get loan template |
| `loans/{loanId}/transactions` | GET | Get loan transactions |
| `loans/{loanId}/guarantors` | GET | Get guarantors |
| `loans/{loanId}/guarantors` | POST | Add guarantor |
| `loans/{loanId}/guarantors/{guarantorId}` | DELETE | Remove guarantor |
### Share Accounts
| Endpoint | Method | Description |
|----------|--------|-------------|
| `shareaccounts` | GET | Get share accounts list |
| `shareaccounts` | POST | Apply for shares |
| `shareaccounts/{accountId}` | GET | Get share account details |
### Beneficiaries
| Endpoint | Method | Description |
|----------|--------|-------------|
| `beneficiaries/tpt` | GET | Get beneficiary list |
| `beneficiaries/tpt` | POST | Create beneficiary |
| `beneficiaries/tpt/template` | GET | Get beneficiary template |
| `beneficiaries/tpt/{beneficiaryId}` | PUT | Update beneficiary |
| `beneficiaries/tpt/{beneficiaryId}` | DELETE | Delete beneficiary |
### Transfers
| Endpoint | Method | Description |
|----------|--------|-------------|
| `accounttransfers` | POST | Make transfer |
| `accounttransfers/template` | GET | Get transfer template |
### Notifications
| Endpoint | Method | Description |
|----------|--------|-------------|
| `notifications` | GET | Get notifications |
| `notifications` | PUT | Mark as read |
### Products
| Endpoint | Method | Description |
|----------|--------|-------------|
| `products/savings` | GET | Get savings products |
| `products/loans` | GET | Get loan products |
| `products/share` | GET | Get share products |
---
## Common Query Parameters
| Parameter | Description | Example |
|-----------|-------------|---------|
| `associations` | Include related data | `all`, `transactions`, `charges` |
| `fields` | Limit response fields | `id,name,status` |
| `offset` | Pagination offset | `0` |
| `limit` | Pagination limit | `20` |
---
## Response Patterns
### Single Entity
```json
{
"id": 1,
"accountNo": "000000001",
"status": {
"id": 300,
"code": "savingsAccountStatusType.active",
"value": "Active"
}
}
```
### List (Paginated)
```json
{
"totalFilteredRecords": 100,
"pageItems": [
{ "id": 1, "name": "Item 1" },
{ "id": 2, "name": "Item 2" }
]
}
```
### Error
```json
{
"developerMessage": "Error details",
"httpStatusCode": "400",
"defaultUserMessage": "User friendly message",
"userMessageGlobalisationCode": "error.msg.code",
"errors": []
}
```
---
## Kotlin Service Constants
```kotlin
// core/network/utils/ApiEndPoints.kt
object ApiEndPoints {
const val AUTHENTICATION = "authentication"
const val CLIENTS = "clients"
const val SAVINGS_ACCOUNTS = "savingsaccounts"
const val SHARE_ACCOUNTS = "shareaccounts"
const val LOANS = "loans"
const val BENEFICIARIES = "beneficiaries"
const val ACCOUNT_TRANSFER = "accounttransfers"
const val REGISTRATION = "registration"
const val USER = "user"
const val PRODUCTS = "products"
const val DEVICE = "device"
}
```
---
## Status Codes Reference
### Savings Account Status
| Code | Value |
|------|-------|
| 100 | Submitted and pending approval |
| 200 | Approved |
| 300 | Active |
| 400 | Withdrawn by applicant |
| 500 | Rejected |
| 600 | Closed |
### Loan Account Status
| Code | Value |
|------|-------|
| 100 | Submitted and pending approval |
| 200 | Approved |
| 300 | Active |
| 400 | Withdrawn by applicant |
| 500 | Rejected |
| 600 | Closed (obligations met) |
| 700 | Overpaid |
---
## Demo Credentials
For testing:
- **Instance**: `gsoc.mifos.community`
- **Username**: `maria`
- **Password**: `password`
- **Tenant**: `default`

View File

@ -1,825 +0,0 @@
# Mifos Mobile - Design System & Component Library
> **Version**: 2.0 (Revolut-Style Vibrant Design)
> **Last Updated**: 2025-12-29
> **Design Philosophy**: Modern Fintech with Trust, Clarity, Speed
---
## 1. Color System
### 1.1 Primary Palette
```
┌─────────────────────────────────────────────────────────────────┐
│ COLOR TOKENS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ PRIMARY GRADIENTS │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ #667EEA │ │ #11998E │ │ #FC466B │ │
│ │ ↓ │ │ ↓ │ │ ↓ │ │
│ │ #764BA2 │ │ #38EF7D │ │ #3F5EFB │ │
│ │ Purple-Blue │ │ Teal-Green │ │ Pink-Blue │ │
│ │ (Primary) │ │ (Secondary) │ │ (Accent) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ SEMANTIC COLORS │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ #00D09C │ │ #FFB800 │ │ #FF4757 │ │
│ │ Success │ │ Warning │ │ Error │ │
│ │ (Teal/Mint) │ │ (Amber) │ │ (Coral Red) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ BACKGROUNDS │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Light Mode │ Dark Mode │ │
│ │ ───────────── │ ───────────── │ │
│ │ Background: #F8F9FA │ Background: #0D1117 │ │
│ │ Surface: #FFFFFF │ Surface: #1A1F2E │ │
│ │ Card: #FFFFFF │ Card: #21262D │ │
│ │ Divider: #E1E4E8 │ Divider: #30363D │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ TEXT COLORS │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Light Mode │ Dark Mode │ │
│ │ ───────────── │ ───────────── │ │
│ │ Primary: #1F2937 │ Primary: #F0F6FC │ │
│ │ Secondary: #6B7280 │ Secondary: #8B949E │ │
│ │ Tertiary: #9CA3AF │ Tertiary: #6E7681 │ │
│ │ Disabled: #D1D5DB │ Disabled: #484F58 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 1.2 Usage Guidelines
| Context | Light Mode | Dark Mode | Gradient |
|---------|------------|-----------|----------|
| Balance Cards | #FFFFFF | #1A1F2E | Primary Gradient background |
| Income Indicator | #00D09C | #00D09C | - |
| Expense Indicator | #FF4757 | #FF4757 | - |
| CTA Buttons | - | - | Primary Gradient |
| Quick Actions | #667EEA | #667EEA | - |
| Links | #667EEA | #764BA2 | - |
---
## 2. Typography
### 2.1 Type Scale
```
┌─────────────────────────────────────────────────────────────────┐
│ TYPOGRAPHY SCALE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ DISPLAY │
│ ════════════════════════════════════════════════════════════ │
│ Display Large 48sp / Bold / -0.5 letter spacing │
│ Display Medium 40sp / Bold / -0.5 letter spacing │
│ Display Small 32sp / Bold / 0 letter spacing │
│ │
│ AMOUNT (Financial Values) │
│ ════════════════════════════════════════════════════════════ │
│ Amount Large 36sp / ExtraBold / -0.5 letter spacing │
│ Amount Medium 28sp / Bold / 0 letter spacing │
│ Amount Small 20sp / SemiBold / 0 letter spacing │
│ │
│ HEADLINES │
│ ════════════════════════════════════════════════════════════ │
│ Headline Large 24sp / Bold / 0 letter spacing │
│ Headline Medium 20sp / SemiBold / 0.15 letter spacing │
│ Headline Small 18sp / Medium / 0.15 letter spacing │
│ │
│ BODY │
│ ════════════════════════════════════════════════════════════ │
│ Body Large 16sp / Regular / 0.5 letter spacing │
│ Body Medium 14sp / Regular / 0.25 letter spacing │
│ Body Small 12sp / Regular / 0.4 letter spacing │
│ │
│ LABELS │
│ ════════════════════════════════════════════════════════════ │
│ Label Large 14sp / Medium / 0.1 letter spacing │
│ Label Medium 12sp / Medium / 0.5 letter spacing │
│ Label Small 10sp / Medium / 0.5 letter spacing │
│ │
│ FONT FAMILY: Inter (Primary) / System Default (Fallback) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 3. Spacing & Layout
### 3.1 Spacing Scale
```
┌─────────────────────────────────────────────────────────────────┐
│ SPACING TOKENS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Base Unit: 4dp │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Token │ Value │ Usage │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ space-0 │ 0dp │ No spacing │ │
│ │ space-1 │ 4dp │ Tight spacing (icons) │ │
│ │ space-2 │ 8dp │ Small gaps │ │
│ │ space-3 │ 12dp │ Default element spacing │ │
│ │ space-4 │ 16dp │ Card padding │ │
│ │ space-5 │ 20dp │ Section spacing │ │
│ │ space-6 │ 24dp │ Large section gaps │ │
│ │ space-8 │ 32dp │ Screen padding horizontal │ │
│ │ space-10 │ 40dp │ Major section breaks │ │
│ │ space-12 │ 48dp │ Hero card padding │ │
│ │ space-16 │ 64dp │ Bottom nav height │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 3.2 Layout Grid
```
┌─────────────────────────────────────────────────────────────────┐
│ LAYOUT GRID │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Screen Margins: 16dp (compact) / 24dp (expanded) │
│ Content Width: 100% - 32dp (16dp each side) │
│ Card Margins: 16dp horizontal │
│ Card Padding: 16dp internal │
│ Card Gap: 12dp between cards │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ 16dp │◀───────── Content Area ─────────▶│ 16dp │ │
│ │ ├────┼──────────────────────────────────┼────┤ │ │
│ │ │ │ ┌────────────────────────────┐ │ │ │ │
│ │ │ │ │ CARD 1 │ │ │ │ │
│ │ │ │ │ (16dp padding) │ │ │ │ │
│ │ │ │ └────────────────────────────┘ │ │ │ │
│ │ │ │ 12dp gap │ │ │ │
│ │ │ │ ┌────────────────────────────┐ │ │ │ │
│ │ │ │ │ CARD 2 │ │ │ │ │
│ │ │ │ └────────────────────────────┘ │ │ │ │
│ │ │ │ │ │ │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 4. Components
### 4.1 HeroBalanceCard
The main balance display at the top of dashboard screens.
```
┌─────────────────────────────────────────────────────────────────┐
│ HERO BALANCE CARD │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │
│ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │
│ │░░ 💰 Total Balance 👁 ░░░░░░│ │
│ │░░ ░░░░░│ │
│ │░░ $12,450.00 ░░░░░│ │
│ │░░ ░░░░░│ │
│ │░░ ┌───────────┐ ┌───────────┐ ░░░░░│ │
│ │░░ │ ▲ +$450 │ │ ▼ -$120 │ ░░░░░│ │
│ │░░ │ Income │ │ Expense │ ░░░░░│ │
│ │░░ └───────────┘ └───────────┘ ░░░░░│ │
│ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • balance: String - Main balance amount │
│ • currency: String - Currency symbol ($, €, etc.) │
│ • income: String - Monthly income │
│ • expense: String - Monthly expense │
│ • isAmountVisible: Boolean - Toggle balance visibility │
│ • onVisibilityToggle: () - Eye icon callback │
│ • gradientColors: List - Background gradient │
│ │
│ Dimensions: │
│ ───────────────────────────────────────────────────────────── │
│ • Height: 180dp │
│ • Corner Radius: 24dp │
│ • Padding: 24dp │
│ • Gradient: Primary (Purple-Blue diagonal) │
│ • Shadow: 8dp blur, 4dp offset, 15% opacity │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.2 QuickActionBar
Horizontal scrollable quick action buttons.
```
┌─────────────────────────────────────────────────────────────────┐
│ QUICK ACTION BAR │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │ 💸 │ │ 📥 │ │ 📱 │ │ 📊 │ │ 🎯 │ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │ │
│ │ Send Request QR Code Analytics Goals │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • actions: List<QuickAction>
│ - icon: ImageVector │
│ - label: String │
│ - onClick: () -> Unit │
│ - badge: String? (optional notification count) │
│ │
│ Dimensions: │
│ ───────────────────────────────────────────────────────────── │
│ • Icon Container: 56dp x 56dp │
│ • Icon Size: 24dp │
│ • Corner Radius: 16dp │
│ • Gap Between Items: 16dp │
│ • Label: 12sp, Medium weight │
│ • Background: Surface color with 8% primary tint │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.3 AccountCard
Compact account summary card with progress indicator.
```
┌─────────────────────────────────────────────────────────────────┐
│ ACCOUNT CARD │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌───┐ │ │
│ │ │ 💵│ Primary Savings ● Active ▶ │ │
│ │ └───┘ ****4521 │ │
│ │ │ │
│ │ $8,200.00 ↗ +$200/mo │ │
│ │ │ │
│ │ ████████████████░░░░░░░░░░░░░░░ 65% to goal │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Variants: │
│ ───────────────────────────────────────────────────────────── │
│ • SAVINGS - Green icon background, positive balance │
│ • LOAN - Blue icon background, negative balance, due date │
│ • SHARE - Purple icon background, share count │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • accountType: AccountType │
│ • accountName: String │
│ • accountNumber: String (masked ****XXXX) │
│ • balance: String │
│ • status: AccountStatus (Active, Dormant, Closed) │
│ • monthlyChange: String? (optional +/- indicator) │
│ • progress: Float? (0.0-1.0 for goal progress) │
│ • progressLabel: String? ("65% to goal") │
│ • onClick: () -> Unit │
│ │
│ Dimensions: │
│ ───────────────────────────────────────────────────────────── │
│ • Height: ~100dp (auto) │
│ • Icon Container: 44dp x 44dp │
│ • Corner Radius: 16dp │
│ • Padding: 16dp │
│ • Progress Bar Height: 6dp │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.4 TransactionItem
Modern transaction list item with category icon.
```
┌─────────────────────────────────────────────────────────────────┐
│ TRANSACTION ITEM │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌───┐ │ │
│ │ │ 🛒│ Amazon Prime -$14.99 │ │
│ │ └───┘ Shopping • Dec 15, 2:34 PM │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Amount Styling: │
│ ───────────────────────────────────────────────────────────── │
│ • Positive (Income): #00D09C, prefix "+" │
│ • Negative (Expense): #FF4757, prefix "-" │
│ • Pending: #6B7280, italic │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • icon: ImageVector or Emoji │
│ • title: String │
│ • subtitle: String (category • timestamp) │
│ • amount: String │
│ • isPositive: Boolean │
│ • isPending: Boolean │
│ • onClick: () -> Unit │
│ │
│ Dimensions: │
│ ───────────────────────────────────────────────────────────── │
│ • Height: 64dp │
│ • Icon Container: 40dp x 40dp │
│ • Icon Background: Category color at 12% opacity │
│ • Corner Radius: 12dp │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.5 InsightCard
AI-powered financial insight display.
```
┌─────────────────────────────────────────────────────────────────┐
│ INSIGHT CARD │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │
│ │░░ ░░│ │
│ │░░ 💡 Weekly Insight ░░│ │
│ │░░ ░░│ │
│ │░░ 📊 You spent 23% less on dining this week! ░░│ │
│ │░░ compared to last week. Keep it up! 🎉 ░░│ │
│ │░░ ░░│ │
│ │░░ 🍔 Dining: $45 → $35 ░░│ │
│ │░░ ░░│ │
│ │░░ ┌────────────┐ ┌────────────┐ ░░│ │
│ │░░ │View Details│ │ Dismiss │ ░░│ │
│ │░░ └────────────┘ └────────────┘ ░░│ │
│ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Variants: │
│ ───────────────────────────────────────────────────────────── │
│ • POSITIVE - Green gradient, celebration emoji │
│ • WARNING - Amber gradient, caution emoji │
│ • INFO - Blue gradient, info emoji │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • type: InsightType (POSITIVE, WARNING, INFO) │
│ • title: String │
│ • message: String │
│ • detail: String? (optional comparison data) │
│ • onViewDetails: () -> Unit │
│ • onDismiss: () -> Unit │
│ • isDismissible: Boolean │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.6 SavingsGoalCard
Gamified savings goal with progress ring.
```
┌─────────────────────────────────────────────────────────────────┐
│ SAVINGS GOAL CARD │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌─────────┐ │ │
│ │ │ ╭───╮ │ 🏖 Vacation Fund │ │
│ │ │ │60%│ │ $1,200 / $2,000 │ │
│ │ │ ╰───╯ │ │ │
│ │ └─────────┘ 🔥 15 day streak │ │
│ │ │ │
│ │ ████████████████░░░░░░░░░░░░░░░ │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Add $50 │ │ View Details │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • emoji: String │
│ • goalName: String │
│ • currentAmount: String │
│ • targetAmount: String │
│ • progress: Float (0.0-1.0) │
│ • streak: Int? (days) │
│ • quickAddAmounts: List<Int> (e.g., [10, 25, 50, 100]) │
│ • onQuickAdd: (amount: Int) -> Unit │
│ • onViewDetails: () -> Unit │
│ │
│ Progress Ring: │
│ ───────────────────────────────────────────────────────────── │
│ • Size: 64dp x 64dp │
│ • Stroke Width: 6dp │
│ • Track Color: Surface variant │
│ • Progress Color: Secondary Gradient │
│ • Center: Percentage text (Bold, 16sp) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.7 BillReminderCard
Upcoming bill payment reminder.
```
┌─────────────────────────────────────────────────────────────────┐
│ BILL REMINDER CARD │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌───┐ │ │
│ │ │ ⚡│ Electricity Bill Due Dec 15 │ │
│ │ └───┘ Pacific Gas & Electric │ │
│ │ │ │
│ │ $85.00 ⚠️ 3 days │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────────┐ │ │
│ │ │ Pay Now │ │ Remind Later │ │ │
│ │ └─────────────┘ └─────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Urgency Indicators: │
│ ───────────────────────────────────────────────────────────── │
│ • Overdue: Red background tint, "⛔ Overdue" │
│ • 1-3 days: Amber background tint, "⚠️ X days" │
│ • 4-7 days: Default surface, "📅 X days" │
│ • 7+ days: Default surface, date only │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • icon: ImageVector or Emoji │
│ • billName: String │
│ • payee: String │
│ • amount: String │
│ • dueDate: LocalDate │
│ • isOverdue: Boolean │
│ • onPayNow: () -> Unit │
│ • onRemindLater: () -> Unit │
│ • onDismiss: () -> Unit │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.8 RecentRecipientChip
Avatar-based recent transfer recipient.
```
┌─────────────────────────────────────────────────────────────────┐
│ RECENT RECIPIENT CHIP │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ JD │ │ MS │ │ AK │ │ RK │ │ + │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ └────┘ │ │
│ │ John Maria Alex Raj Add │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • initials: String (2 characters) │
│ • name: String (display name, max 6 chars) │
│ • avatarUrl: String? (optional profile image) │
│ • backgroundColor: Color (random from preset palette) │
│ • onClick: () -> Unit │
│ │
│ Dimensions: │
│ ───────────────────────────────────────────────────────────── │
│ • Avatar Size: 48dp x 48dp │
│ • Corner Radius: 50% (circle) │
│ • Label: 12sp, max 6 characters with ellipsis │
│ • Horizontal Spacing: 16dp │
│ │
│ Add Button Variant: │
│ ───────────────────────────────────────────────────────────── │
│ • Dashed border instead of solid │
│ • "+" icon in center │
│ • "Add" label below │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.9 AmountInputField
Large amount input with quick-add chips.
```
┌─────────────────────────────────────────────────────────────────┐
│ AMOUNT INPUT FIELD │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ $ 150.00 │ │
│ │ ═════════ │ │
│ │ │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │ +10 │ │ +50 │ │ +100 │ │ +500 │ │ │
│ │ └──────┘ └──────┘ └──────┘ └──────┘ │ │
│ │ │ │
│ │ Available: $8,200.00 │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • value: String │
│ • onValueChange: (String) -> Unit │
│ • currency: String ("$", "€", etc.) │
│ • availableBalance: String │
│ • quickAmounts: List<Int> (e.g., [10, 50, 100, 500]) │
│ • onQuickAmountClick: (Int) -> Unit │
│ • error: String? (e.g., "Exceeds available balance") │
│ │
│ Styling: │
│ ───────────────────────────────────────────────────────────── │
│ • Amount Font: 36sp, ExtraBold │
│ • Currency: 24sp, Medium │
│ • Quick Amount Chips: Outlined, 12sp │
│ • Available Label: 14sp, Secondary color │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.10 TrustBadge
Security and encryption indicator.
```
┌─────────────────────────────────────────────────────────────────┐
│ TRUST BADGE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Inline Variant: │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 🔒 256-bit encryption • Instant transfer │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Compact Variant: │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 🔒 Secured │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Last Login Variant: │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Last login: Today 9:41 AM • iPhone 15 Pro │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • variant: TrustBadgeVariant (INLINE, COMPACT, LAST_LOGIN) │
│ • message: String │
│ • icon: ImageVector (default: Lock) │
│ • timestamp: String? (for LAST_LOGIN) │
│ • device: String? (for LAST_LOGIN) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.11 FilterChipRow
Horizontal filter selection chips.
```
┌─────────────────────────────────────────────────────────────────┐
│ FILTER CHIP ROW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌───────┐ ┌─────────┐ ┌───────┐ ┌───────┐ │ │
│ │ │ All ✓ │ │ Savings │ │ Loans │ │ Share │ │ │
│ │ └───────┘ └─────────┘ └───────┘ └───────┘ │ │
│ │ SELECTED DEFAULT DEFAULT DEFAULT │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ States: │
│ ───────────────────────────────────────────────────────────── │
│ • Default: Outlined border, transparent background │
│ • Selected: Filled with Primary color, white text, checkmark │
│ • Disabled: 40% opacity │
│ │
│ Props: │
│ ───────────────────────────────────────────────────────────── │
│ • filters: List<FilterOption>
│ - label: String │
│ - isSelected: Boolean │
│ - count: Int? (optional badge) │
│ • onFilterSelected: (index: Int) -> Unit │
│ • singleSelect: Boolean (true) or multiSelect: Boolean │
│ │
│ Dimensions: │
│ ───────────────────────────────────────────────────────────── │
│ • Height: 36dp │
│ • Corner Radius: 18dp (pill shape) │
│ • Horizontal Padding: 16dp │
│ • Gap: 8dp │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 5. Navigation
### 5.1 Bottom Navigation Bar
```
┌─────────────────────────────────────────────────────────────────┐
│ BOTTOM NAVIGATION BAR (4-Tab) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌─────┐ ┌─────┐ ┌─────────┐ ┌─────┐ │ │
│ │ │ ⌂ │ │ ☰ │ │ 💸 │ │ 👤 │ │ │
│ │ │ │ │ │ │ ═════ │ │ │ │ │
│ │ └─────┘ └─────┘ │ FAB │ └─────┘ │ │
│ │ Home Accounts └─────────┘ Profile │ │
│ │ ACTIVE INACTIVE CENTER INACTIVE │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Specifications: │
│ ───────────────────────────────────────────────────────────── │
│ • Height: 64dp │
│ • Background: Surface with elevation (4dp) │
│ • Active Icon: Primary color, filled variant │
│ • Inactive Icon: Secondary text color, outlined variant │
│ • Label: 12sp, shown on active tab only │
│ • FAB: 56dp, elevated, gradient background, glow effect │
│ • Safe Area: Bottom padding for gesture navigation │
│ │
│ FAB Design: │
│ ───────────────────────────────────────────────────────────── │
│ • Size: 56dp x 56dp │
│ • Elevation: 8dp │
│ • Y-Offset: -16dp (floats above bar) │
│ • Background: Primary Gradient │
│ • Shadow: 16dp blur, primary color at 30% │
│ • Icon: Send Money (💸), 28dp, white │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 6. Animations & Micro-interactions
### 6.1 Animation Tokens
```
┌─────────────────────────────────────────────────────────────────┐
│ ANIMATION SPECIFICATIONS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Durations: │
│ ───────────────────────────────────────────────────────────── │
│ • Instant: 100ms (micro-interactions) │
│ • Fast: 200ms (button presses, toggles) │
│ • Normal: 300ms (screen transitions) │
│ • Slow: 500ms (complex animations) │
│ • Very Slow: 800ms (celebrations, onboarding) │
│ │
│ Easings: │
│ ───────────────────────────────────────────────────────────── │
│ • Standard: cubic-bezier(0.4, 0.0, 0.2, 1) │
│ • Decelerate: cubic-bezier(0.0, 0.0, 0.2, 1) │
│ • Accelerate: cubic-bezier(0.4, 0.0, 1.0, 1) │
│ • Spring: spring(dampingRatio=0.7, stiffness=400) │
│ │
│ Key Animations: │
│ ───────────────────────────────────────────────────────────── │
│ • Balance reveal: Fade + Scale (0.9 → 1.0), 300ms │
│ • Card press: Scale (1.0 → 0.98), 100ms │
│ • Pull-to-refresh: Rotate loading icon, continuous │
│ • Transaction success: Checkmark draw + confetti, 500ms │
│ • Amount input: Haptic feedback on each digit │
│ • Goal progress: Circular fill animation, 800ms │
│ • Streak badge: Bounce + glow pulse, 300ms │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 7. Accessibility
### 7.1 Guidelines
```
┌─────────────────────────────────────────────────────────────────┐
│ ACCESSIBILITY REQUIREMENTS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Touch Targets: │
│ ───────────────────────────────────────────────────────────── │
│ • Minimum size: 48dp x 48dp │
│ • Recommended: 56dp x 56dp for primary actions │
│ • Spacing between targets: 8dp minimum │
│ │
│ Color Contrast: │
│ ───────────────────────────────────────────────────────────── │
│ • Text on background: 4.5:1 minimum (AA) │
│ • Large text: 3:1 minimum │
│ • Non-text elements: 3:1 minimum │
│ • Focus indicators: 3:1 against adjacent colors │
│ │
│ Screen Reader Support: │
│ ───────────────────────────────────────────────────────────── │
│ • All interactive elements: contentDescription │
│ • Balance amounts: Read as "Balance: 12,450 dollars" │
│ • Status indicators: Read status (Active, Pending) │
│ • Progress: Read as "60 percent complete" │
│ │
│ Motion Preferences: │
│ ───────────────────────────────────────────────────────────── │
│ • Honor "Reduce Motion" system setting │
│ • Provide instant transitions when motion reduced │
│ • Keep essential feedback animations │
│ │
│ Font Scaling: │
│ ───────────────────────────────────────────────────────────── │
│ • Support up to 200% text scaling │
│ • Use flexible layouts that don't break │
│ • Scroll when content overflows │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 8. Dark Mode
### 8.1 Theme Switching
```
┌─────────────────────────────────────────────────────────────────┐
│ DARK MODE SPECIFICATIONS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Automatic Elements: │
│ ───────────────────────────────────────────────────────────── │
│ • Background: #F8F9FA#0D1117
│ • Surface/Cards: #FFFFFF#1A1F2E
│ • Primary Text: #1F2937#F0F6FC
│ • Secondary Text: #6B7280#8B949E
│ • Dividers: #E1E4E8#30363D
│ │
│ Preserved Colors (Same in both modes): │
│ ───────────────────────────────────────────────────────────── │
│ • Success: #00D09C
│ • Error: #FF4757
│ • Warning: #FFB800
│ • Primary Gradient: #667EEA#764BA2
│ │
│ Adjusted Elements: │
│ ───────────────────────────────────────────────────────────── │
│ • Card shadows: Removed in dark mode │
│ • Gradient intensity: Slightly reduced (85% opacity) │
│ • Icon backgrounds: Increased contrast │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## Changelog
| Date | Version | Change |
|------|---------|--------|
| 2025-12-29 | 2.0 | Complete redesign with Revolut-style vibrant design system |

View File

@ -1,427 +0,0 @@
# Implementation Patterns - Mifos Mobile
> **Purpose**: Reference patterns for consistent implementation across features
> **Last Updated**: 2025-12-26
---
## Architecture Overview
```
┌─────────────────────────────────────────────────────────────────────┐
│ MIFOS MOBILE ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ FEATURE │ │ DATA │ │ NETWORK │ │
│ │ (UI) │───▶│ (Repository) │───▶│ (Service) │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ViewModel │ │Repository│ │ Ktorfit │ │
│ │ (MVI) │ │ Impl │ │ Service │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Screen │ │DataState │ │ Fineract │ │
│ │(Compose) │ │ Flow │ │ API │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 1. MVI ViewModel Pattern
### Base Structure
```kotlin
internal class FeatureViewModel(
private val repository: FeatureRepository,
private val userPreferences: UserPreferencesRepository,
) : BaseViewModel<FeatureState, FeatureEvent, FeatureAction>(
initialState = FeatureState()
) {
init {
loadInitialData()
}
override fun handleAction(action: FeatureAction) {
when (action) {
is FeatureAction.Retry -> loadInitialData()
is FeatureAction.OnItemClick -> handleItemClick(action.id)
is FeatureAction.OnRefresh -> refreshData()
}
}
private fun loadInitialData() {
viewModelScope.launch {
repository.getData()
.collect { dataState ->
handleDataState(dataState)
}
}
}
private fun handleDataState(dataState: DataState<Data>) {
when (dataState) {
is DataState.Loading -> updateState {
it.copy(uiState = FeatureScreenState.Loading)
}
is DataState.Success -> updateState {
it.copy(
uiState = FeatureScreenState.Success,
data = dataState.data
)
}
is DataState.Error -> updateState {
it.copy(uiState = FeatureScreenState.Error(Res.string.error_message))
}
}
}
private fun handleItemClick(id: Long) {
sendEvent(FeatureEvent.NavigateToDetail(id))
}
private fun updateState(update: (FeatureState) -> FeatureState) {
mutableStateFlow.update(update)
}
}
```
### State Definition
```kotlin
@Immutable
data class FeatureState(
val clientId: Long? = null,
val data: List<Item> = emptyList(),
val isRefreshing: Boolean = false,
val uiState: FeatureScreenState = FeatureScreenState.Loading,
)
sealed interface FeatureScreenState {
data object Loading : FeatureScreenState
data object Success : FeatureScreenState
data class Error(val message: StringResource) : FeatureScreenState
data object Empty : FeatureScreenState
}
```
### Event Definition (One-time actions)
```kotlin
sealed interface FeatureEvent {
data class NavigateToDetail(val id: Long) : FeatureEvent
data object NavigateBack : FeatureEvent
data class ShowSnackbar(val message: StringResource) : FeatureEvent
}
```
### Action Definition (User interactions)
```kotlin
sealed interface FeatureAction {
data object Retry : FeatureAction
data object OnRefresh : FeatureAction
data class OnItemClick(val id: Long) : FeatureAction
// Internal actions (from system, not user)
sealed interface Internal : FeatureAction {
data class ReceiveData(val dataState: DataState<Data>) : Internal
}
}
```
---
## 2. Repository Pattern
### Interface
```kotlin
interface FeatureRepository {
fun getData(): Flow<DataState<List<Data>>>
fun getById(id: Long): Flow<DataState<Data>>
suspend fun create(payload: CreatePayload): DataState<Unit>
suspend fun update(id: Long, payload: UpdatePayload): DataState<Unit>
suspend fun delete(id: Long): DataState<Unit>
}
```
### Implementation
```kotlin
class FeatureRepositoryImpl(
private val service: FeatureService,
private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
) : FeatureRepository {
override fun getData(): Flow<DataState<List<Data>>> = flow {
emit(DataState.Loading)
try {
val result = service.fetchData().first()
emit(DataState.Success(result))
} catch (e: Exception) {
emit(DataState.Error(e.message ?: "Unknown error"))
}
}.flowOn(dispatcher)
override suspend fun create(payload: CreatePayload): DataState<Unit> {
return withContext(dispatcher) {
try {
service.create(payload)
DataState.Success(Unit)
} catch (e: Exception) {
DataState.Error(e.message ?: "Failed to create")
}
}
}
}
```
---
## 3. Service Pattern (Ktorfit)
```kotlin
interface FeatureService {
@GET(ApiEndPoints.FEATURE)
fun getData(): Flow<List<DataDto>>
@GET(ApiEndPoints.FEATURE + "/{id}")
fun getById(@Path("id") id: Long): Flow<DataDto>
@GET(ApiEndPoints.FEATURE + "/{id}")
fun getWithAssociations(
@Path("id") id: Long,
@Query("associations") associations: String?,
): Flow<DataWithAssociations>
@POST(ApiEndPoints.FEATURE)
suspend fun create(@Body payload: CreatePayload): HttpResponse
@PUT(ApiEndPoints.FEATURE + "/{id}")
suspend fun update(
@Path("id") id: Long,
@Body payload: UpdatePayload,
): HttpResponse
@DELETE(ApiEndPoints.FEATURE + "/{id}")
suspend fun delete(@Path("id") id: Long): HttpResponse
companion object {
const val ID = "id"
}
}
```
---
## 4. Screen Pattern
```kotlin
@Composable
fun FeatureScreen(
viewModel: FeatureViewModel = koinViewModel(),
onNavigateBack: () -> Unit,
onNavigateToDetail: (Long) -> Unit,
) {
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
// Handle one-time events
LaunchedEffect(Unit) {
viewModel.eventFlow.collect { event ->
when (event) {
is FeatureEvent.NavigateBack -> onNavigateBack()
is FeatureEvent.NavigateToDetail -> onNavigateToDetail(event.id)
}
}
}
FeatureScreenContent(
state = state,
onAction = viewModel::sendAction,
)
}
@Composable
private fun FeatureScreenContent(
state: FeatureState,
onAction: (FeatureAction) -> Unit,
) {
Scaffold(
topBar = {
MifosTopAppBar(
title = stringResource(Res.string.feature_title),
onNavigationClick = { onAction(FeatureAction.OnNavigateBack) },
)
}
) { paddingValues ->
Box(modifier = Modifier.padding(paddingValues)) {
when (state.uiState) {
is FeatureScreenState.Loading -> LoadingContent()
is FeatureScreenState.Success -> SuccessContent(
data = state.data,
onItemClick = { onAction(FeatureAction.OnItemClick(it)) }
)
is FeatureScreenState.Error -> ErrorContent(
message = state.uiState.message,
onRetry = { onAction(FeatureAction.Retry) }
)
is FeatureScreenState.Empty -> EmptyContent()
}
}
}
}
```
---
## 5. Navigation Pattern
```kotlin
// Route definition
@Serializable
data object FeatureRoute
// Or with parameters
@Serializable
data class FeatureDetailRoute(val id: Long)
// Navigation extension
fun NavGraphBuilder.featureScreen(
onNavigateBack: () -> Unit,
onNavigateToDetail: (Long) -> Unit,
) {
composable<FeatureRoute> {
FeatureScreen(
onNavigateBack = onNavigateBack,
onNavigateToDetail = onNavigateToDetail,
)
}
}
// NavController extension
fun NavController.navigateToFeature() {
navigate(FeatureRoute)
}
fun NavController.navigateToFeatureDetail(id: Long) {
navigate(FeatureDetailRoute(id))
}
```
---
## 6. DI Module Pattern
```kotlin
val featureModule = module {
viewModelOf(::FeatureViewModel)
}
```
---
## 7. DataState Pattern
```kotlin
sealed interface DataState<out T> {
data object Loading : DataState<Nothing>
data class Success<T>(val data: T) : DataState<T>
data class Error(val message: String) : DataState<Nothing>
}
```
---
## 8. Error Handling Pattern
```kotlin
// In ViewModel
private fun handleError(exception: Exception) {
val errorMessage = when (exception) {
is HttpException -> when (exception.response.status.value) {
401 -> Res.string.error_unauthorized
404 -> Res.string.error_not_found
500 -> Res.string.error_server
else -> Res.string.error_unknown
}
is IOException -> Res.string.error_network
else -> Res.string.error_unknown
}
updateState { it.copy(uiState = FeatureScreenState.Error(errorMessage)) }
}
```
---
## 9. Pull-to-Refresh Pattern
```kotlin
@Composable
private fun FeatureContent(
state: FeatureState,
onRefresh: () -> Unit,
) {
PullToRefreshBox(
isRefreshing = state.isRefreshing,
onRefresh = onRefresh,
) {
LazyColumn {
items(state.data) { item ->
ItemCard(item = item)
}
}
}
}
```
---
## 10. Form Validation Pattern
```kotlin
// In ViewModel
private fun validateForm(): Boolean {
val errors = mutableListOf<ValidationError>()
if (state.amount <= 0) {
errors.add(ValidationError.InvalidAmount)
}
if (state.accountId == null) {
errors.add(ValidationError.AccountRequired)
}
if (errors.isNotEmpty()) {
updateState { it.copy(validationErrors = errors) }
return false
}
return true
}
sealed interface ValidationError {
data object InvalidAmount : ValidationError
data object AccountRequired : ValidationError
}
```
---
## Best Practices
1. **State Immutability**: Always use `@Immutable` on state classes
2. **Single Source of Truth**: State lives in ViewModel only
3. **Unidirectional Data Flow**: UI → Action → ViewModel → State → UI
4. **Separation of Concerns**: Keep layers independent
5. **Error Handling**: Always handle Loading, Success, Error states
6. **Resource Strings**: Use `StringResource` for all user-facing text
7. **Flow Collection**: Use `collectAsStateWithLifecycle()` in Compose
8. **Internal Visibility**: Use `internal` for feature-internal classes

View File

@ -1,139 +0,0 @@
# Mockups Directory Structure
> **Purpose**: Store and organize UI mockup images for each feature
> **Last Updated**: 2025-01-04
---
## Directory Structure
```
features/
└── [feature-name]/
└── mockups/
├── PROMPTS.md # AI design tool prompts
├── design-tokens.json # Structured design tokens
├── FIGMA_LINKS.md # Figma export URLs
├── dummy/ # Placeholder images (reference)
│ ├── 01-screen-name.png
│ ├── 02-screen-name.png
│ └── ...
└── prod/ # Production mockups (actual designs)
├── 01-screen-name.png
├── 02-screen-name.png
└── ...
```
---
## Usage
### For Designers
1. **Generate designs** using prompts from `PROMPTS.md`:
- Google Stitch: [stitch.withgoogle.com](https://stitch.withgoogle.com)
- Figma: Use Figma AI or manual design
2. **Export designs** as PNG/JPG at:
- 1x (375px width for mobile)
- 2x (750px) - optional for high-res
- 3x (1125px) - optional for high-res
3. **Save to `prod/`** with matching filenames:
- Replace `dummy/01-login-screen.png`
- With `prod/01-login-screen.png`
4. **Update `FIGMA_LINKS.md`** with Figma URLs
### For Developers (Claude)
When implementing screens, I will:
1. Check `prod/` first for actual designs
2. Fall back to `dummy/` for placeholder reference
3. Use `design-tokens.json` for colors, spacing, typography
4. Reference screen naming for navigation flow
---
## Naming Convention
```
[order]-[screen-name].png
Examples:
01-login-screen.png
02-registration-screen.png
03-forgot-password.png
```
### Order Prefix
- `01-09`: Main screens
- `10-19`: Secondary screens
- `20-29`: Modals/dialogs
- `30-39`: Empty/error states
- `40-49`: Dark mode variants
---
## Feature Screen Inventory
| Feature | Screens | dummy/ | prod/ |
|---------|:-------:|:------:|:-----:|
| auth | 6 | ✅ | ⏳ |
| home | 5 | ✅ | ⏳ |
| accounts | 4 | ✅ | ⏳ |
| savings-account | 6 | ✅ | ⏳ |
| loan-account | 7 | ✅ | ⏳ |
| share-account | 6 | ✅ | ⏳ |
| beneficiary | 6 | ✅ | ⏳ |
| transfer | 6 | ✅ | ⏳ |
| recent-transaction | 6 | ✅ | ⏳ |
| notification | 5 | ✅ | ⏳ |
| settings | 9 | ✅ | ⏳ |
| passcode | 7 | ✅ | ⏳ |
| guarantor | 8 | ✅ | ⏳ |
| qr | 7 | ✅ | ⏳ |
| location | 8 | ✅ | ⏳ |
| client-charge | 9 | ✅ | ⏳ |
| dashboard | 7 | ✅ | ⏳ |
**Legend**: ✅ Complete | ⏳ Pending | ❌ Missing
---
## Dark Mode Variants
For dark mode, add `-dark` suffix:
```
01-login-screen.png # Light mode
01-login-screen-dark.png # Dark mode
```
---
## Image Specifications
| Property | Value |
|----------|-------|
| Format | PNG (preferred) or JPG |
| Width | 375px (1x) / 750px (2x) |
| Color Profile | sRGB |
| Compression | Optimized for web |
---
## Workflow
```
1. Read PROMPTS.md for feature
2. Generate in Stitch/Figma
3. Export as PNG
4. Save to prod/ folder
5. Update FIGMA_LINKS.md
6. Commit & push
```

View File

@ -1,799 +0,0 @@
# Accounts - API Reference
> **Base URL**: `https://tt.mifos.community/fineract-provider/api/v1/self/`
> **Authentication**: Basic Auth with `Fineract-Platform-TenantId` header
> **Last Updated**: 2025-12-29
---
## Authentication Headers
All endpoints require:
```
Headers:
Authorization: Basic {base64EncodedAuthenticationKey}
Fineract-Platform-TenantId: {tenantId}
Content-Type: application/json
```
---
## 1. Client Accounts Overview
### GET /self/clients/{clientId}/accounts
**Purpose**: Fetch all account summaries for account listing
**Request**:
```
GET /self/clients/123/accounts
```
**Optional Query Parameters**:
| Parameter | Type | Description |
|-----------|------|-------------|
| fields | String | Filter by account type: "savingsAccounts", "loanAccounts", "shareAccounts" |
**Response**:
```json
{
"savingsAccounts": [
{
"id": 1001,
"accountNo": "SA-0001234567",
"productId": 1,
"productName": "Wallet Savings",
"status": {
"id": 300,
"code": "savingsAccountStatusType.active",
"value": "Active",
"submittedAndPendingApproval": false,
"approved": true,
"rejected": false,
"withdrawnByApplicant": false,
"active": true,
"closed": false
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"accountBalance": 12500.00,
"depositType": {
"id": 100,
"code": "depositAccountType.savingsDeposit",
"value": "Savings"
},
"lastActiveTransactionDate": [2025, 12, 29]
}
],
"loanAccounts": [
{
"id": 2001,
"accountNo": "LA-0009876543",
"productId": 2,
"productName": "Personal Loan",
"status": {
"id": 300,
"code": "loanStatusType.active",
"value": "Active",
"active": true
},
"loanType": {
"id": 1,
"code": "accountType.individual",
"value": "Individual"
},
"principal": 10000.00,
"loanBalance": 6750.00,
"amountPaid": 3250.00,
"inArrears": false,
"currency": {
"code": "USD",
"displaySymbol": "$"
}
}
],
"shareAccounts": [
{
"id": 3001,
"accountNo": "SH-0005678901",
"productId": 3,
"productName": "Equity Shares",
"status": {
"id": 300,
"code": "shareAccountStatusType.active",
"value": "Active",
"active": true
},
"totalApprovedShares": 100,
"totalPendingForApprovalShares": 0,
"currency": {
"code": "USD",
"displaySymbol": "$"
}
}
]
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class ClientAccounts(
val loanAccounts: List<LoanAccount> = emptyList(),
val savingsAccounts: List<SavingAccount>? = emptyList(),
val shareAccounts: List<ShareAccount> = emptyList(),
) {
fun recurringSavingsAccounts(): List<SavingAccount>
fun nonRecurringSavingsAccounts(): List<SavingAccount>
}
```
**Status**: Implemented in ClientService
---
## 2. Savings Account Details with Transactions
### GET /self/savingsaccounts/{accountId}
**Purpose**: Fetch savings account details with transaction history
**Request**:
```
GET /self/savingsaccounts/1001?associations=transactions
```
**Query Parameters**:
| Parameter | Type | Description |
|-----------|------|-------------|
| associations | String | Include related data: "transactions", "charges", "all" |
**Response**:
```json
{
"id": 1001,
"accountNo": "SA-0001234567",
"clientId": 123,
"clientName": "John Doe",
"savingsProductId": 1,
"savingsProductName": "Wallet Savings",
"status": {
"id": 300,
"code": "savingsAccountStatusType.active",
"value": "Active",
"active": true
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"nominalAnnualInterestRate": 4.5,
"summary": {
"totalDeposits": 15000.00,
"totalWithdrawals": 2500.00,
"totalInterestEarned": 125.00,
"accountBalance": 12625.00
},
"transactions": [
{
"id": 10001,
"transactionType": {
"id": 1,
"code": "savingsAccountTransactionType.deposit",
"value": "Deposit",
"deposit": true,
"withdrawal": false,
"interestPosting": false,
"feeDeduction": false
},
"accountId": 1001,
"accountNo": "SA-0001234567",
"date": [2025, 12, 29],
"currency": {
"code": "USD",
"displaySymbol": "$"
},
"amount": 4500.00,
"runningBalance": 12625.00,
"reversed": false,
"submittedOnDate": [2025, 12, 29]
},
{
"id": 10002,
"transactionType": {
"id": 2,
"code": "savingsAccountTransactionType.withdrawal",
"value": "Withdrawal",
"deposit": false,
"withdrawal": true,
"interestPosting": false,
"feeDeduction": false
},
"accountId": 1001,
"accountNo": "SA-0001234567",
"date": [2025, 12, 28],
"currency": {
"code": "USD",
"displaySymbol": "$"
},
"amount": 150.00,
"runningBalance": 8125.00,
"reversed": false
}
]
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class SavingsWithAssociations(
val id: Long? = null,
val accountNo: String? = null,
val depositType: DepositType? = null,
val externalId: String? = null,
val clientId: Int? = null,
val clientName: String? = null,
val savingsProductId: Int? = null,
val savingsProductName: String? = null,
val status: Status? = null,
val timeline: TimeLine? = null,
val currency: Currency? = null,
val nominalAnnualInterestRate: Double? = null,
val summary: Summary? = null,
val transactions: List<Transactions> = emptyList(),
)
@Serializable
data class Transactions(
val id: Int? = null,
val transactionType: TransactionType? = null,
val accountId: Int? = null,
val accountNo: String? = null,
val date: List<Int> = emptyList(),
val currency: Currency? = null,
val paymentDetailData: PaymentDetailData? = null,
val amount: Double? = null,
val runningBalance: Double? = null,
val reversed: Boolean? = null,
val submittedOnDate: List<Int>? = null,
)
```
**Status**: Implemented in SavingAccountsListService
---
## 3. Loan Account Details with Transactions
### GET /self/loans/{loanId}
**Purpose**: Fetch loan account details with transaction history
**Request**:
```
GET /self/loans/2001?associations=transactions
```
**Query Parameters**:
| Parameter | Type | Description |
|-----------|------|-------------|
| associations | String | Include: "repaymentSchedule", "transactions", "all" |
**Response**:
```json
{
"id": 2001,
"accountNo": "LA-0009876543",
"clientId": 123,
"clientName": "John Doe",
"loanProductId": 2,
"loanProductName": "Personal Loan",
"status": {
"id": 300,
"code": "loanStatusType.active",
"value": "Active",
"active": true
},
"loanType": {
"id": 1,
"code": "accountType.individual",
"value": "Individual"
},
"currency": {
"code": "USD",
"displaySymbol": "$",
"decimalPlaces": 2
},
"principal": 10000.00,
"approvedPrincipal": 10000.00,
"numberOfRepayments": 12,
"interestRatePerPeriod": 1.0,
"summary": {
"principalDisbursed": 10000.00,
"principalPaid": 3250.00,
"principalOutstanding": 6750.00,
"interestCharged": 600.00,
"interestPaid": 400.00,
"interestOutstanding": 200.00,
"totalExpectedRepayment": 10600.00,
"totalRepayment": 3650.00,
"totalOutstanding": 6950.00
},
"transactions": [
{
"id": 20001,
"officeId": 1,
"officeName": "Head Office",
"type": {
"id": 2,
"code": "loanTransactionType.repayment",
"value": "Repayment",
"disbursement": false,
"repaymentAtDisbursement": false,
"repayment": true
},
"date": [2025, 12, 15],
"currency": {
"code": "USD",
"displaySymbol": "$"
},
"amount": 900.00,
"principalPortion": 800.00,
"interestPortion": 100.00,
"feeChargesPortion": 0.00,
"penaltyChargesPortion": 0.00,
"outstandingLoanBalance": 6750.00,
"reversed": false
}
],
"inArrears": false
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class LoanWithAssociations(
val id: Int? = null,
val accountNo: String? = null,
val externalId: String? = null,
val status: Status? = null,
val clientId: Int? = null,
val clientName: String? = null,
val loanProductId: Int? = null,
val loanProductName: String? = null,
val loanType: LoanType? = null,
val currency: Currency? = null,
val principal: Double? = null,
val approvedPrincipal: Double? = null,
val numberOfRepayments: Int? = null,
val interestRatePerPeriod: Double? = null,
val timeline: Timeline? = null,
val summary: Summary? = null,
val repaymentSchedule: RepaymentSchedule? = null,
val transactions: List<Transaction?>? = arrayListOf(),
val inArrears: Boolean? = null,
)
```
**Status**: Implemented in LoanAccountsListService
---
## 4. Share Account Details
### GET /self/shareaccounts/{accountId}
**Purpose**: Fetch share account details with purchased shares history
**Request**:
```
GET /self/shareaccounts/3001?associations=all
```
**Query Parameters**:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| associations | String | "all" | Include related data |
**Response**:
```json
{
"id": 3001,
"accountNo": "SH-0005678901",
"clientId": 123,
"clientName": "John Doe",
"productId": 3,
"productName": "Equity Shares",
"status": {
"id": 300,
"code": "shareAccountStatusType.active",
"value": "Active",
"active": true
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"timeline": {
"submittedOnDate": [2024, 1, 15],
"approvedDate": [2024, 1, 20],
"activatedDate": [2024, 1, 25]
},
"totalApprovedShares": 100,
"totalPendingForApprovalShares": 0,
"purchasedShares": [
{
"id": 30001,
"purchasedDate": [2024, 1, 25],
"numberOfShares": 50,
"purchasedPrice": 10.00,
"status": {
"id": 300,
"code": "purchaseStatusType.approved",
"value": "Approved"
},
"type": {
"id": 500,
"code": "purchaseType.purchased",
"value": "Purchase"
},
"amount": 500.00,
"chargeAmount": 5.00,
"amountPaid": 505.00
}
],
"summary": {
"totalApprovedShares": 100,
"totalPendingShares": 0
}
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class ShareAccountWithAssociations(
val id: Long = 0,
val accountNo: String? = null,
val clientId: Long? = null,
val clientName: String? = null,
val productId: Long? = null,
val productName: String? = null,
val status: Status? = null,
val currency: Currency? = null,
val timeline: Timeline? = null,
val totalApprovedShares: Int? = null,
val totalPendingForApprovalShares: Int? = null,
val purchasedShares: List<Transactions> = emptyList(),
val summary: Summary? = null,
)
// Share Transactions
@Serializable
data class Transactions(
val id: Long? = null,
val purchasedDate: List<Int> = emptyList(),
val numberOfShares: Int? = null,
val purchasedPrice: Double? = null,
val status: Status? = null,
val type: EnumOptionData? = null,
val amount: Double? = null,
val chargeAmount: Double? = null,
val amountPaid: Double? = null,
)
```
**Status**: Implemented in ShareAccountService
---
## 5. Recent Transactions
### GET /self/clients/{clientId}/transactions
**Purpose**: Fetch recent transactions across all accounts
**Request**:
```
GET /self/clients/123/transactions?offset=0&limit=50
```
**Query Parameters**:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| offset | Int | 0 | Pagination offset |
| limit | Int | 50 | Number of records per page |
**Response**:
```json
{
"totalFilteredRecords": 150,
"pageItems": [
{
"id": 10001,
"officeId": 1,
"officeName": "Head Office",
"type": {
"id": 1,
"code": "savingsAccountTransactionType.deposit",
"value": "Deposit",
"deposit": true,
"withdrawal": false,
"interestPosting": false,
"feeDeduction": false
},
"date": [2025, 12, 29],
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"amount": 4500.00,
"submittedOnDate": [2025, 12, 29],
"reversed": false
}
]
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class Page<T>(
val totalFilteredRecords: Int = 0,
val pageItems: List<T> = emptyList(),
)
@Serializable
data class Transaction(
val id: Long? = null,
val officeId: Long? = null,
val officeName: String? = null,
val type: Type,
val date: List<Int> = emptyList(),
val currency: Currency? = null,
val amount: Double? = null,
val submittedOnDate: List<Int> = emptyList(),
val reversed: Boolean? = null,
)
```
**Status**: Implemented in RecentTransactionsService
---
## 6. Savings Transaction Details
### GET /self/savingsaccounts/{accountId}/transactions/{transactionId}
**Purpose**: Fetch detailed information about a specific savings transaction
**Request**:
```
GET /self/savingsaccounts/1001/transactions/10001
```
**Response**:
```json
{
"id": 10001,
"officeId": 1,
"officeName": "Head Office",
"transactionType": {
"id": 1,
"code": "savingsAccountTransactionType.deposit",
"value": "Deposit",
"deposit": true,
"withdrawal": false,
"interestPosting": false,
"feeDeduction": false
},
"date": [2025, 12, 29],
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"amount": 4500.00,
"accountNo": "SA-0001234567",
"runningBalance": 12625.00,
"reversed": false,
"manuallyReversed": false,
"externalId": "EXT-12345",
"submittedOnDate": [2025, 12, 29]
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class TransactionDetails(
val id: Long? = null,
val officeId: Long? = null,
val officeName: String? = null,
val type: Type? = null,
val date: List<Int> = emptyList(),
val currency: Currency? = null,
val amount: Double? = null,
val submittedOnDate: List<Int> = emptyList(),
val reversed: Boolean? = null,
val accountNo: String? = null,
val manuallyReversed: Boolean? = null,
val externalId: String? = null,
val outstandingLoanBalance: Double? = null,
val runningBalance: Double? = null,
val principalPortion: Double? = null,
val interestPortion: Double? = null,
val feeChargesPortion: Double? = null,
val penaltyChargesPortion: Double? = null,
) {
val isCredit: Boolean
get() { /* logic based on type value */ }
}
```
**Status**: Implemented in SavingAccountsListService
---
## 7. Loan Transaction Details
### GET /self/loans/{loanId}/transactions/{transactionId}
**Purpose**: Fetch detailed information about a specific loan transaction
**Request**:
```
GET /self/loans/2001/transactions/20001
```
**Response**:
```json
{
"id": 20001,
"officeId": 1,
"officeName": "Head Office",
"transactionType": {
"id": 2,
"code": "loanTransactionType.repayment",
"value": "Repayment",
"disbursement": false,
"repayment": true
},
"date": [2025, 12, 15],
"currency": {
"code": "USD",
"displaySymbol": "$",
"decimalPlaces": 2
},
"amount": 900.00,
"accountNo": "LA-0009876543",
"reversed": false,
"manuallyReversed": false,
"externalId": "LN-EXT-20001",
"outstandingLoanBalance": 6750.00,
"principalPortion": 800.00,
"interestPortion": 100.00,
"feeChargesPortion": 0.00,
"penaltyChargesPortion": 0.00
}
```
**Status**: Implemented in LoanAccountsListService
---
## API Summary Table
| Endpoint | Method | Service | Repository | Priority |
|----------|--------|---------|------------|----------|
| /self/clients/{id}/accounts | GET | ClientService | AccountsRepository | P0 |
| /self/savingsaccounts/{id} | GET | SavingAccountsListService | SavingsAccountRepository | P0 |
| /self/loans/{id} | GET | LoanAccountsListService | LoanRepository | P0 |
| /self/shareaccounts/{id} | GET | ShareAccountService | ShareAccountRepository | P0 |
| /self/clients/{id}/transactions | GET | RecentTransactionsService | RecentTransactionRepository | P0 |
| /self/savingsaccounts/{id}/transactions/{txId} | GET | SavingAccountsListService | SavingsAccountRepository | P1 |
| /self/loans/{id}/transactions/{txId} | GET | LoanAccountsListService | LoanRepository | P1 |
---
## Common Data Models
### Currency
```kotlin
@Serializable
data class Currency(
val code: String? = null,
val name: String? = null,
val decimalPlaces: Int? = null,
val displaySymbol: String? = null,
val nameCode: String? = null,
val displayLabel: String? = null,
)
```
### Status (Common pattern across account types)
```kotlin
@Serializable
data class Status(
val id: Int? = null,
val code: String? = null,
val value: String? = null,
val submittedAndPendingApproval: Boolean? = null,
val approved: Boolean? = null,
val rejected: Boolean? = null,
val withdrawnByApplicant: Boolean? = null,
val active: Boolean? = null,
val closed: Boolean? = null,
val matured: Boolean? = null,
val overpaid: Boolean? = null,
)
```
### TransactionType
```kotlin
@Serializable
data class TransactionType(
val id: Int? = null,
val code: String? = null,
val value: String? = null,
val deposit: Boolean? = null,
val dividendPayout: Boolean? = null,
val withdrawal: Boolean? = null,
val interestPosting: Boolean? = null,
val feeDeduction: Boolean? = null,
val initiateTransfer: Boolean? = null,
val approveTransfer: Boolean? = null,
val withdrawTransfer: Boolean? = null,
val rejectTransfer: Boolean? = null,
val overdraftFee: Boolean? = null,
)
```
---
## Error Responses
| Status Code | Error | Description | User Message |
|-------------|-------|-------------|--------------|
| 400 | Bad Request | Invalid request payload | "Please check your input" |
| 401 | Unauthorized | Invalid/expired token | "Please login again" |
| 403 | Forbidden | Insufficient permissions | "Access denied" |
| 404 | Not Found | Resource doesn't exist | "Account not found" |
| 500 | Server Error | Internal server error | "Service unavailable" |
**Error Response Format**:
```json
{
"developerMessage": "Detailed error for debugging",
"httpStatusCode": "404",
"defaultUserMessage": "Account not found",
"userMessageGlobalisationCode": "error.msg.account.not.found",
"errors": []
}
```
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Initial API documentation based on existing implementation |

View File

@ -1,543 +0,0 @@
# Accounts - Feature Specification
> **Purpose**: Unified account listing with type-specific filtering for savings, loans, and shares
> **User Value**: Browse and manage all financial accounts with powerful filtering capabilities
> **Last Updated**: 2025-12-29
> **Status**: Production Design
---
## 1. Overview
### 1.1 Feature Summary
The Accounts feature provides a comprehensive view of user accounts organized by type (Savings, Loan, Share). Users can browse account lists, apply multi-criteria filters (by account type and status), view transactions history, and access detailed transaction information. The feature supports pull-to-refresh for real-time data updates and maintains filter state across sessions.
### 1.2 User Stories
- As a user, I want to view all my savings accounts in one place
- As a user, I want to filter accounts by type (wallet, bank, group, NB)
- As a user, I want to filter accounts by status (active, pending, closed, matured, approved)
- As a user, I want to see transaction history for each account
- As a user, I want to filter transactions by type (credit/debit) and duration
- As a user, I want to view detailed information about a specific transaction
- As a user, I want to refresh account data with pull-to-refresh gesture
### 1.3 Design Principles
- **Consistency**: Same filter pattern across all account types
- **Efficiency**: Quick access to filtered views with minimal taps
- **Clarity**: Clear distinction between account types and statuses
- **Responsiveness**: Real-time updates via pull-to-refresh
---
## 2. Screen Layout
### 2.1 Accounts List Screen
```
+-------------------------------------------------------------+
| <- Savings Accounts ... |
+-------------------------------------------------------------+
| |
| +-------------------------------------------------------+ |
| | [FILTER ICON] Filter | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Wallet Savings Account | |
| | SA-0001234567 | Active | |
| | Balance: $12,500.00 | |
| | Interest: 4.5% p.a. | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Bank Savings Account | |
| | SA-0001234568 | Active | |
| | Balance: $8,750.00 | |
| | Interest: 3.2% p.a. | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Group Savings Account | |
| | SA-0001234569 | Pending | |
| | Balance: $0.00 | |
| | Interest: 2.5% p.a. | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | [Powered by Mifos] | |
| +-------------------------------------------------------+ |
+-------------------------------------------------------------+
```
### 2.2 Filter Bottom Sheet
```
+-------------------------------------------------------------+
| Filters |
+-------------------------------------------------------------+
| |
| [Reset Filters] [Apply] |
| |
| --------------------------------------------------------- |
| |
| Account Type (2 selected) v |
| --------------------------------------------------------- |
| [ ] Wallet Account |
| [x] Bank Account |
| [x] Group Account |
| [ ] NB Account |
| |
| --------------------------------------------------------- |
| |
| Account Status (1 selected) v |
| --------------------------------------------------------- |
| [x] Active |
| [ ] Pending |
| [ ] Closed |
| [ ] Matured |
| [ ] Approved |
| |
+-------------------------------------------------------------+
```
### 2.3 Transaction History Screen
```
+-------------------------------------------------------------+
| <- Transaction History |
+-------------------------------------------------------------+
| |
| [Filter] |
| |
| Today |
| +-------------------------------------------------------+ |
| | v Deposit + $4,500.00 | |
| | Dec 29, 2025 | |
| +-------------------------------------------------------+ |
| | ^ Withdrawal - $150.00 | |
| | Dec 29, 2025 | |
| +-------------------------------------------------------+ |
| |
| Yesterday |
| +-------------------------------------------------------+ |
| | v Interest Posting + $125.50 | |
| | Dec 28, 2025 | |
| +-------------------------------------------------------+ |
| | ^ Transfer Out - $500.00 | |
| | Dec 28, 2025 | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | [Powered by Mifos] | |
| +-------------------------------------------------------+ |
+-------------------------------------------------------------+
```
### 2.4 Transaction Details Screen
```
+-------------------------------------------------------------+
| <- Transaction Details |
+-------------------------------------------------------------+
| |
| +------------------+ |
| | v | |
| | (Credit Icon) | |
| +------------------+ |
| |
| $4,500.00 |
| Deposit |
| |
| +-------------------------------------------------------+ |
| | Transaction ID 12345 | |
| | ------------------------------------------------- | |
| | Date Dec 29, 2025 | |
| | ------------------------------------------------- | |
| | Status Success | |
| | ------------------------------------------------- | |
| | Account Ref SA-0001234567 | |
| | ------------------------------------------------- | |
| | Type Deposit | |
| | ------------------------------------------------- | |
| | External ID EXT-12345 | |
| | ------------------------------------------------- | |
| | | |
| | BREAKDOWN | |
| | ------------------------------------------------- | |
| | Principal $4,400.00 | |
| | ------------------------------------------------- | |
| | Interest $100.00 | |
| | ------------------------------------------------- | |
| | Fees $0.00 | |
| | ------------------------------------------------- | |
| | Penalties $0.00 | |
| | ------------------------------------------------- | |
| | | |
| | Balance $12,500.00 | |
| +-------------------------------------------------------+ |
| |
+-------------------------------------------------------------+
```
---
## 3. Sections Table
| Section | Description | Components |
|---------|-------------|------------|
| Top Bar | Navigation and screen title | Back button, title (Savings/Loan/Share Accounts) |
| Filter Action | Opens filter bottom sheet | Filter button with icon |
| Account List | Scrollable list of accounts | Account cards with balance, status, interest rate |
| Filter Bottom Sheet | Multi-criteria filter dialog | Type filters, status filters, reset/apply buttons |
| Transaction List | Grouped by date | Transaction items with type, amount, date |
| Transaction Filter | Transaction-specific filters | Type (Credit/Debit), Duration (1mo/3mo/6mo/1yr/2yr) |
| Transaction Details | Full transaction information | Header, details table, breakdown section |
| Powered Footer | Branding footer | Mifos branding card |
---
## 4. User Interactions Table
| Interaction | Action | Result |
|-------------|--------|--------|
| Tap Back Button | OnNavigateBack | Navigate to previous screen |
| Tap Filter Button | ToggleFilter | Open filter bottom sheet |
| Tap Account Card | OnAccountClicked | Navigate to account details |
| Toggle Checkbox | ToggleCheckbox | Update filter selection |
| Tap Reset Filters | ResetFilters | Clear all filter selections |
| Tap Apply Filters | GetFilterResults | Apply filters and close sheet |
| Pull to Refresh | Refresh | Reload account data from API |
| Tap Transaction Item | OnTransactionClick | Navigate to transaction details |
| Expand/Collapse Filter Section | ToggleTypeExpanded/ToggleStatusExpanded | Show/hide filter options |
---
## 5. State Model
### 5.1 AccountsState (from AccountsViewModel.kt)
```kotlin
internal data class AccountsState(
val isRefreshing: Boolean = false,
val checkboxOptions: List<CheckboxStatus> = emptyList(),
val selectedFilters: List<CheckboxStatus> = emptyList(),
val accountType: AccountType = AccountType.SAVINGS,
val toggleFilterDialog: Boolean = false,
val accountTypeFiltersCount: Int? = 0,
val accountStatusFiltersCount: Int? = 0,
val refreshSignal: Long = Clock.System.now().epochSeconds,
val dialogState: DialogState? = null,
val uiState: ScreenUiState = ScreenUiState.Loading,
val isTypeExpanded: Boolean = true,
val isStatusExpanded: Boolean = true,
) {
sealed interface DialogState {
data class Error(val message: String) : DialogState
data object Filters : DialogState
}
val isAnyFilterSelected = checkboxOptions.any { it.isChecked }
}
```
### 5.2 AccountTransactionState (from TransactionViewModel.kt)
```kotlin
internal data class AccountTransactionState(
val clientId: Long,
val accountType: String,
val accountId: Long,
val isRefreshing: Boolean = false,
val data: List<UiTransaction> = emptyList(),
val filteredData: Map<String, List<UiTransaction>> = emptyMap(),
val dialogState: DialogState? = null,
val checkboxOptions: List<TransactionCheckboxStatus> = emptyList(),
val selectedFilters: List<TransactionCheckboxStatus> = emptyList(),
val toggleFilterDialog: Boolean = false,
val accountTypeFiltersCount: Int? = 0,
val accountDurationFiltersCount: Int? = 0,
val selectedRadioButton: StringResource? = null,
val isFilteredRecordsEmpty: Boolean = false,
val networkStatus: Boolean = false,
val uiState: ScreenUiState? = ScreenUiState.Loading,
) {
sealed interface DialogState {
data class Error(val message: String) : DialogState
data object Filters : DialogState
}
val isAnyFilterSelected = checkboxOptions.any { it.isChecked } || selectedRadioButton != null
}
```
### 5.3 TransactionDetailsState (from TransactionDetailsViewModel.kt)
```kotlin
data class TransactionDetailsState(
val transactionId: Long,
val accountId: Long,
val accountType: String,
val uiState: ScreenUiState = ScreenUiState.Loading,
val transaction: UiTransactionDetails? = null,
)
```
### 5.4 Actions
```kotlin
// Accounts Actions
sealed interface AccountsAction {
data object ToggleFilter : AccountsAction
data object ToggleTypeExpanded : AccountsAction
data object ToggleStatusExpanded : AccountsAction
data object ResetFilters : AccountsAction
data object DismissDialog : AccountsAction
data object GetFilterResults : AccountsAction
data object OnNavigateBack : AccountsAction
data object Refresh : AccountsAction
data object RefreshCompleted : AccountsAction
data class OnAccountClicked(val accountId: Long, val accountType: String) : AccountsAction
data class SetCheckboxFilterList(val checkBoxList: List<CheckboxStatus>, val accountType: String) : AccountsAction
data class ToggleCheckbox(val label: StringResource, val type: FilterType) : AccountsAction
}
// Transaction Actions
sealed interface AccountTransactionAction {
data object Refresh : AccountTransactionAction
data object DismissDialog : AccountTransactionAction
data object OnNavigateBackClick : AccountTransactionAction
data object ToggleFilter : AccountTransactionAction
data object ResetFilters : AccountTransactionAction
data object GetFilterResults : AccountTransactionAction
data class ReceiveNetworkResult(val isOnline: Boolean) : AccountTransactionAction
data class OnTransactionClick(val id: Long?) : AccountTransactionAction
data class ToggleCheckbox(val label: StringResource, val type: TransactionFilterType) : AccountTransactionAction
data class ToggleRadioButton(val label: StringResource) : AccountTransactionAction
}
// Transaction Details Actions
sealed interface TransactionDetailsAction {
data object OnNavigateBack : TransactionDetailsAction
data object Retry : TransactionDetailsAction
}
```
### 5.5 Events
```kotlin
// Accounts Events
sealed interface AccountsEvent {
data object NavigateBack : AccountsEvent
data class AccountClicked(val accountId: Long, val accountType: String) : AccountsEvent
}
// Transaction Events
sealed interface AccountTransactionEvent {
data object OnNavigateBack : AccountTransactionEvent
data class NavigateToDetails(val id: String) : AccountTransactionEvent
}
// Transaction Details Events
sealed interface TransactionDetailsEvent {
data object NavigateBack : TransactionDetailsEvent
}
```
---
## 6. Filter Options
### 6.1 Savings Account Filters
| Filter Type | Options |
|-------------|---------|
| Account Type | Wallet Account, Bank Account, Group Account, NB Account |
| Account Status | Active, Pending, Closed, Matured, Approved |
### 6.2 Loan Account Filters
| Filter Type | Options |
|-------------|---------|
| Account Type | Personal, Bronze |
| Account Status | Active, Approval Pending, Closed, Disburse, Overpaid, In Arrears, Withdrawn, Matured, Rejected |
### 6.3 Share Account Filters
| Filter Type | Options |
|-------------|---------|
| Account Type | Wallet Account, Bank Account |
| Account Status | Active, Approval Pending, Closed, Disburse, Overpaid, In Arrears, Withdrawn, Matured, Rejected |
### 6.4 Transaction Filters
| Filter Type | Options |
|-------------|---------|
| Transaction Type | Credit, Debit |
| Duration | Past Month, Past 3 Months, Past 6 Months, Past 1 Year, Past 2 Years |
---
## 7. API Requirements Table
| Endpoint | Method | Purpose | Priority |
|----------|--------|---------|----------|
| /self/clients/{clientId}/accounts | GET | Fetch all accounts | P0 |
| /self/savingsaccounts/{accountId} | GET | Fetch savings details with transactions | P0 |
| /self/loans/{loanId} | GET | Fetch loan details with transactions | P0 |
| /self/shareaccounts/{accountId} | GET | Fetch share account details | P0 |
| /self/clients/{clientId}/transactions | GET | Fetch recent transactions | P0 |
| /self/savingsaccounts/{accountId}/transactions/{transactionId} | GET | Fetch savings transaction details | P1 |
| /self/loans/{loanId}/transactions/{transactionId} | GET | Fetch loan transaction details | P1 |
---
## 8. Edge Cases & Error Handling
| Scenario | UI Behavior | Recovery |
|----------|-------------|----------|
| No internet | Show network error state | Retry button, auto-retry on reconnect |
| API timeout | Show error state with message | Pull-to-refresh or Retry button |
| No accounts | Show empty state | Display "No accounts found" message |
| No transactions | Show empty state | Display "No transactions found" |
| No filtered results | Show empty filtered state | Display "No matching transactions" |
| Invalid transaction ID | Show error state | Navigate back or retry |
| Auth expired | Navigate to login | Re-authenticate |
| Partial data load | Show available data | Silent background retry |
---
## 9. Performance Requirements
| Metric | Target | Implementation |
|--------|--------|----------------|
| First paint | < 500ms | Skeleton loading |
| Data load | < 2s | Parallel API calls |
| Filter apply | < 100ms | Client-side filtering |
| Scroll | 60fps | LazyColumn with keys |
| Pull-to-refresh | Responsive | Optimistic UI update |
---
## 10. Navigation Routes
```kotlin
// Account Navigation
@Serializable
data class AccountNavRoute(val accountType: String)
// Transaction Navigation
@Serializable
data class AccountTransactionsNavRoute(
val accountId: Long,
val accountType: String,
)
// Transaction Details Navigation
@Serializable
data class TransactionDetailsNavRoute(
val transactionId: String,
val accountType: String,
val accountId: Long,
)
```
---
## 11. Data Models
### 11.1 CheckboxStatus
```kotlin
data class CheckboxStatus(
val statusLabel: StringResource,
val isChecked: Boolean = false,
val type: FilterType = FilterType.ACCOUNT_STATUS,
)
enum class FilterType {
ACCOUNT_TYPE,
ACCOUNT_STATUS,
}
```
### 11.2 TransactionCheckboxStatus
```kotlin
data class TransactionCheckboxStatus(
val statusLabel: StringResource,
val isChecked: Boolean = false,
val type: TransactionFilterType = TransactionFilterType.TRANSACTION_TYPE,
)
enum class TransactionFilterType {
TRANSACTION_TYPE,
DURATION,
}
```
### 11.3 UiTransaction
```kotlin
data class UiTransaction(
val id: Long?,
val date: List<Int>,
val amount: Double?,
val type: TransactionType? = null,
val typeValue: String? = null,
val isCredit: Boolean?,
val currency: String,
)
```
### 11.4 UiTransactionDetails
```kotlin
data class UiTransactionDetails(
val id: Long?,
val date: List<Int>,
val amount: Double?,
val status: String,
val typeValue: String? = null,
val isCredit: Boolean?,
val currency: String,
val accountNo: String? = null,
val principal: Double? = null,
val interest: Double? = null,
val fees: Double? = null,
val penalties: Double? = null,
val externalId: String? = null,
val outstandingBalance: Double? = null,
)
```
---
## 12. Credit/Debit Logic
```kotlin
fun getTransactionCreditStatus(transactionType: TransactionType?): Boolean {
return transactionType?.run {
when {
deposit == true -> true
dividendPayout == true -> false
withdrawal == true -> false
interestPosting == true -> true
feeDeduction == true -> false
initiateTransfer == true -> false
approveTransfer == true -> false
withdrawTransfer == true -> false
rejectTransfer == true -> true
overdraftFee == true -> false
else -> true
}
} ?: false
}
```
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Initial specification based on existing implementation |

View File

@ -1,122 +0,0 @@
# Accounts - Implementation Status
> **Last Updated**: 2025-12-29
> **Overall Status**: ✅ Done
---
## Implementation Checklist
- [x] SPEC.md created
- [x] API.md created
- [x] Network: Services exist (SavingAccountsListService, LoanAccountsListService, ShareAccountService)
- [x] Data: Repositories exist (SavingsAccountRepository, LoanRepository, ShareAccountRepository)
- [x] Feature: ViewModels + Screens
- [x] Navigation: Routes registered
- [x] DI: Modules registered
- [x] STATUS.md updated
---
## Layer Status
| Layer | Status | Files |
|-------|--------|-------|
| Network | ✅ | SavingAccountsListService.kt, LoanAccountsListService.kt, ShareAccountService.kt |
| Data | ✅ | SavingsAccountRepository.kt, LoanRepository.kt, ShareAccountRepository.kt |
| Feature | ✅ | AccountsViewModel.kt, AccountsScreen.kt, TransactionViewModel.kt, TransactionScreen.kt, TransactionDetailsViewModel.kt, TransactionDetailsScreen.kt |
| DI | ✅ | AccountsModule.kt |
| Navigation | ✅ | AccountNavigation.kt, AccountsTransactionNavigation.kt, TransactionDetailsNavigation.kt |
---
## Files
### Network Layer
- `core/network/services/SavingAccountsListService.kt`
- `core/network/services/LoanAccountsListService.kt`
- `core/network/services/ShareAccountService.kt`
### Data Layer
- `core/data/repository/SavingsAccountRepository.kt`
- `core/data/repositoryImpl/SavingsAccountRepositoryImp.kt`
- `core/data/repository/LoanRepository.kt`
- `core/data/repositoryImpl/LoanRepositoryImp.kt`
- `core/data/repository/ShareAccountRepository.kt`
- `core/data/repositoryImpl/ShareAccountRepositoryImp.kt`
### Feature Layer
- `feature/accounts/accounts/AccountsViewModel.kt`
- `feature/accounts/accounts/AccountsScreen.kt`
- `feature/accounts/accounts/AccountNavigation.kt`
- `feature/accounts/accountTransactions/TransactionViewModel.kt` (AccountsTransactionViewModel)
- `feature/accounts/accountTransactions/TransactionScreen.kt`
- `feature/accounts/accountTransactions/AccountsTransactionNavigation.kt`
- `feature/accounts/transactionDetail/TransactionDetailsViewModel.kt`
- `feature/accounts/transactionDetail/TransactionDetailsScreen.kt`
- `feature/accounts/transactionDetail/TransactionDetailsNavigation.kt`
- `feature/accounts/component/FilterSection.kt`
- `feature/accounts/model/CheckboxStatus.kt`
- `feature/accounts/model/TransactionCheckboxStatus.kt`
- `feature/accounts/model/FilterType.kt`
- `feature/accounts/model/TransactionFilterType.kt`
- `feature/accounts/utils/StatusUtils.kt`
- `feature/accounts/di/AccountsModule.kt`
---
## Implementation Details
### ViewModels
#### AccountsViewModel
- **Purpose**: Manages the account screen state, handling filter operations, navigation, and refreshing logic
- **State**: AccountsState (filter options, dialog visibility, account type, refresh signals)
- **Actions**: ToggleFilter, ResetFilters, GetFilterResults, Refresh, ToggleCheckbox, DismissDialog, OnAccountClicked, OnNavigateBack
- **Events**: AccountClicked, NavigateBack
#### AccountsTransactionViewModel (TransactionViewModel)
- **Purpose**: Manages account transactions screen state and transaction filtering
- **Repositories Used**: SavingsAccountRepository, LoanRepository, ShareAccountRepository, RecentTransactionRepository
- **State**: AccountTransactionState (transactions, filters, dialog state, network status)
- **Actions**: ToggleFilter, ResetFilters, GetFilterResults, Refresh, ToggleCheckbox, ToggleRadioButton, OnTransactionClick
- **Events**: OnNavigateBack, NavigateToDetails
- **Features**: Transaction type filtering (Credit/Debit), date range filtering, network monitoring
#### TransactionDetailsViewModel
- **Purpose**: Manages transaction detail screen state and fetches transaction details
- **Repositories Used**: SavingsAccountRepository, LoanRepository
- **State**: TransactionDetailsState (transaction details, account info, UI state)
- **Actions**: OnNavigateBack, Retry
- **Events**: NavigateBack
### Screens
#### AccountsScreen
- **Purpose**: Displays list of accounts (Savings, Loan, Share) with filtering and pull-to-refresh
- **Features**: Account filtering by type and status, refresh signal handling
- **Dialog Support**: Filter dialog with checkbox and apply/reset buttons
#### TransactionScreen
- **Purpose**: Displays transactions for a selected account with advanced filtering
- **Features**: Filter by transaction type (Credit/Debit) and date range (1 month to 2 years)
- **Dialog Support**: Filter dialog with checkboxes and radio buttons
- **Error Handling**: Network error and server error states
#### TransactionDetailsScreen
- **Purpose**: Displays detailed information about a specific transaction
- **Features**: Shows transaction amount, date, type, balance, and breakdown (principal, interest, fees, penalties)
---
## Gaps
None identified.
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Initial status documentation |

View File

@ -1,254 +0,0 @@
# Accounts - Figma First Draft Prompts
> **Tool**: Figma First Draft (Shift+I in Figma)
> **Style**: Premium Fintech, Financial Command Center
> **Format**: Natural language prompts optimized for Figma AI
---
## How to Use
1. Open Figma → Create new design file
2. Press `Shift + I` or click "Actions" → "First Draft"
3. Copy each prompt below
4. Generate → Iterate → Refine
---
## Screen 1: Main Accounts View
```
Design a modern mobile accounts dashboard for "Mifos Mobile" fintech app that serves as a financial command center.
At the top, show "My Accounts" as the title with search, quick actions, and notification icons on the right. Add a filter button.
Create a horizontal tab bar with 5 tabs: All, Savings, Loans, Shares, and Goals. The "All" tab should be selected with a pill-shaped indicator below it.
Design a stunning hero card with a purple gradient background displaying the user's net worth of $18,450.00 in large white text. Add an eye icon to toggle visibility. Show two stat chips below: "+$1,250 This Month" in green and "-$380 Expenses" in a softer color. Include a Financial Health Score section with a circular progress ring showing 85 out of 100 with "EXCELLENT" rating and "+5 from last month" indicator.
Add a Spending Analytics section with a "This Week" dropdown. Show "$1,240 spent" prominently with "-12% vs last week" in green. Include a bar chart showing daily spending for Mon through Sun, with today's bar having a special dotted outline. Below the chart, add horizontal scrolling category chips: Food $320 (26%), Transport $180 (15%), Shopping $450 (36%), Bills $290 (23%) - each with a mini progress bar.
Create an AI Insights section with cards that have a subtle gradient border. Show a lightbulb icon with suggestions like "You could save $85/month by switching to a cheaper internet plan" with "Explore Options" and "Dismiss" buttons.
Design a Savings Accounts section showing 3 accounts with a total of $12,500. Add a "7-day streak!" badge with a fire emoji and "+$850 this month". Each account card should be white with rounded corners and swipeable. Show Primary Savings with a wallet icon, ****4521, $8,200.00 balance, and a goal progress bar at 65% showing "$8,200 / $12,600". Include gamification stats: fire emoji "7 days streak", trophy "3 goals", lightning "Auto-save ON $50/week".
Add a Loan Accounts section showing outstanding total of $6,200 and "Debt-free in 18 months" projection. Show Personal Loan with -$4,500 in red, 60% progress bar, next payment $350 due Jan 15 with "Schedule Payment" and "Pay Now" buttons.
Create an Upcoming Bills section with an overdue electricity bill showing a red urgency border, "$85.00", "OVERDUE - Was due Dec 28" with pulsing indicator, and "PAY NOW" and "Snooze" buttons. Show other upcoming bills with amber indicators.
At the bottom, add navigation with Home, Accounts (selected), a floating action button for Transfer in the center that pops up above the nav bar, and Profile.
Style it like Revolut or N26 - premium, data-rich, with purple as the primary accent color.
```
---
## Screen 2: Goals Tab View
```
Design a savings goals dashboard for a banking app when the Goals tab is selected.
Keep the same header and tab bar, but now show Goals as the selected tab.
Create a gradient hero card showing Goals Overview with key stats: 4 Active goals, 2 Achieved, 1 Paused, and $20,600 Total Goal amount. Show an overall progress bar at 62% with "$12,500 saved of $20,600 target".
Add an Achievements section with a horizontal row of badges. Show earned badges (7-day streak with fire, $5K saved with diamond, Goal Master with target) in full color with a golden glow. Show a Super Saver badge at 55% progress in grayscale with a progress ring. Show locked badges with a lock icon and question marks.
Create an Active Goals section with a "+ Create Goal" button. Show the Emergency Fund goal with a shield emoji, 65% progress ring, "$8,200 / $12,600", a "7-day streak" indicator with fire, and "Est. complete: Mar 2025". Include an auto-save info card showing "$50/week on Fridays" with Edit and Pause buttons.
Show the Bali Trip 2025 goal with a palm tree emoji, 45% progress ring, "$3,500 / $8,000", and an "Boost available!" callout. Add a suggestion card: "Add $200 now to reach goal 2 weeks earlier!" with "Boost Now" and "Maybe Later" buttons.
Add an Achieved Goals section with celebration emoji. Show completed goals like "New Laptop - $1,500 saved - Completed Dec 2024" with checkmarks.
```
---
## Screen 3: Spending Category Drill-Down
```
Design a category detail screen when the user taps on a spending category like Food & Dining.
Show a back arrow, "Food & Dining" as the title with a food emoji, and a Share button. Add a "This Week" dropdown to change the time period.
Create a hero section showing "$320.45 spent this week" prominently. Include a line chart showing the spending trend across the week. Add a comparison indicator showing "+15% vs last week" and a budget tracker showing "Budget: $400/week" with a progress bar at 80%.
Design a Sub-Categories section breaking down the spending: Restaurants $185 (58%), Coffee & Cafes $68.50 (21%), Groceries $45.95 (14%), Fast Food $21.00 (7%). Each should have a progress bar showing its percentage.
Add a Recent Transactions section grouped by date. For Today, show transactions like "Pizza Palace -$24.50, Restaurants, 2:30 PM, Visa ****4521" with appropriate category icons. For Yesterday, show "Whole Foods -$45.95" and "McDonald's -$12.50".
Include an AI Insight card at the bottom with a lightbulb: "You spent 58% on restaurants this week. Cooking at home 2 more days could save ~$50" with "Set Cooking Goal" and "Dismiss" buttons.
```
---
## Screen 4: Loading State
```
Design a loading skeleton screen for the accounts dashboard.
Keep the header visible with "My Accounts" but show shimmer placeholders for the filter tabs.
Create a hero card skeleton with the gradient background shape but shimmer placeholders where the net worth balance and stat chips would be. Show a shimmer circle where the health score ring would appear.
Show shimmer rectangles for the analytics section - bars for the chart and pill shapes for the category chips.
Display account card skeletons with shimmer for the icon circle on the left, text lines in the middle, and balance on the right.
The shimmer should have a subtle wave animation moving left to right. Use light gray gradients for the placeholder areas. Stagger the animation start times for visual interest. Make it feel premium and polished, not jarring.
```
---
## Screen 5: Empty State
```
Design an empty state for the accounts screen when a user has no accounts yet.
Show the same header and tab bar with all tabs visible.
In the center, display a friendly illustration of a briefcase or portfolio floating gently with a subtle up-down animation.
Show "Start Your Financial Journey" as a bold headline centered below the illustration. Add descriptive text: "Open your first account and take control of your finances with Mifos Mobile."
Create a "Suggested For You" section with two cards:
1. "Open Savings Account" with a bank icon, "Start saving with 4.5% APY", "Min. deposit: $0 • No monthly fees", and an "Open Now" button
2. "Join Investment Club" with a chart icon, "Community shares with 3% dividends", "Min. shares: 1 @ $50", and a "Learn More" button
Add a text link at the bottom: "Explore All Account Types →"
Make it feel encouraging and welcoming, like an opportunity rather than emptiness.
```
---
## Screen 6: Error State
```
Design an error state screen for when the accounts fail to load.
Keep the header and tabs visible normally.
In the center, show a cloud with an X icon illustration in a soft coral/red tint to indicate something went wrong without being alarming.
Display "Something Went Wrong" as the main heading in bold text.
Add explanatory text: "We couldn't load your accounts right now. Please check your connection and try again."
Create a "Try Again" button with a purple gradient background.
Below, add a "Check Network Settings" text link for users who need additional help.
Keep it calm and reassuring - not panic-inducing. The user should feel confident the app will work once the issue is resolved.
```
---
## Screen 7: Offline Mode
```
Design an offline state for the accounts screen showing cached data.
At the very top, add a slim warning banner in soft amber/yellow showing a no-wifi antenna icon and "You're offline" with a "Reconnect" button on the right.
Show the main header with "My Accounts" and add "Last updated 2 hours ago" as a subtitle in gray text.
Display the rest of the accounts content but at reduced opacity (about 70%) to indicate it's cached data. Add "(Cached)" labels to section headers.
Show the Net Worth card with a desaturated overlay and a "Data may be outdated" warning message.
For the Spending Analytics section, show an "Unavailable" badge and a placeholder message: "Data requires internet connection."
Display the account cards normally but with a banner at the top: "Read-only mode • Cannot make transactions". Disable the swipe actions visually.
The user should understand they can still see their data but it might not be current and they can't perform actions.
```
---
## Component Prompts
### Net Worth Hero Card
```
Design a financial net worth card for a premium banking app.
Use a beautiful diagonal gradient from purple #667EEA to deeper purple #764BA2. Make it full width with generous rounded corners (24px).
Show "NET WORTH" as a small white label with an eye icon to toggle balance visibility.
Display the main balance "$18,450.00" in large white bold text, centered, about 36sp font size.
Below, add two pill-shaped stat chips with semi-transparent white backgrounds: one showing an up arrow with "+$1,250 This Month" and another showing a down arrow with "-$380 Expenses".
Include a Financial Health Score section with a circular progress ring showing 85 out of 100 with "EXCELLENT" rating below it and "+5 from last month" change indicator.
Add a subtle shadow that uses the gradient colors at low opacity to create a glowing effect.
```
### Spending Analytics Chart
```
Design a weekly spending analytics section for a banking dashboard.
Create a bar chart with 7 bars representing Monday through Sunday. Each bar should be about 24px wide with the primary purple gradient color. Today's bar should have a special dotted outline to indicate the current day.
The chart height should be about 120px. Show the day labels below each bar.
Add a touch interaction where tapping a bar shows a tooltip with the exact spending amount for that day.
Below the chart, add horizontally scrolling category chips. Each chip shows a category emoji (like a burger for Food), the amount ($320), and the percentage (26%). Include a mini progress bar within each chip.
Animate the bars growing from the bottom when the section appears, with a staggered animation.
```
### AI Insight Card
```
Design an AI-powered insight card for a fintech app.
Create a card with a subtle gradient border (about 1px) that hints at the app's primary colors. Give the card a very light gradient background (5% opacity).
On the left, show a lightbulb icon indicating it's an AI suggestion.
In the middle, display the insight text: "You could save $85/month by switching to a cheaper internet plan."
At the bottom or right, add two action buttons: "Explore Options" as a primary action and "Dismiss" as a secondary/outlined action.
Make the card dismissible with a swipe-right gesture. Add a subtle animation when it appears, sliding in from the right.
```
### Account Card with Gamification
```
Design an enhanced bank account card with gamification elements.
Create a white card with soft shadows and 20px rounded corners.
On the left, show a circular icon container with a light gradient background (15% opacity) containing a wallet or bank icon.
In the middle section, display the account name "Primary Savings" in medium weight and the masked account number "****4521" in smaller gray text below.
On the right, align the balance "$8,200.00" in a larger, bold style with a change indicator "+$200 this month" in green below it.
Add a goal progress section showing an emoji (like a target), the goal name "Emergency Fund", a progress bar at 65%, and the amounts "$8,200 / $12,600".
At the bottom, include a row of gamification stats: fire emoji with "7 days streak", trophy emoji with "3 goals reached", and lightning bolt with "Auto-save ON $50/week".
Make the entire card swipeable to reveal quick action buttons.
```
---
## Tips for Figma First Draft
1. **Iterate**: Generate once, then refine with follow-up prompts
2. **Colors**: Mention "purple accent #667EEA" for consistency
3. **Reference**: Say "like Revolut" or "N26-style" for context
4. **States**: Ask for "show loading, empty, and error states"
5. **Responsive**: Mention "393px width for mobile" for correct sizing
---
## After Generation
1. Review generated designs for consistency
2. Create a color style library
3. Build component variants
4. Link screens with prototype connections
5. Export and update `FIGMA_LINKS.md`

View File

@ -1,354 +0,0 @@
# Accounts - Google Stitch Prompts
> **Tool**: [Google Stitch](https://stitch.withgoogle.com)
> **Style**: Material Design 3, Financial Command Center
> **Format**: Copy each prompt block directly into Stitch
---
## Design System Reference
```
Primary Gradient: #667EEA#764BA2
Secondary Gradient: #11998E#38EF7D
Success/Credit: #00D09C
Error/Debit: #FF4757
Warning: #FFB800
Text Primary: #1F2937
Text Secondary: #6B7280
Surface: #FFFFFF
Screen Size: 393 x 852 pixels (Android)
```
---
## Screen 1: Main Accounts View
```
Mobile accounts dashboard screen, Material Design 3, fintech app, 393x852px
Top Bar:
- "My Accounts" title 24sp bold, #1F2937
- Right side: search, quick actions, notification icons
- Filter button right aligned
Tab Bar:
- 5 tabs: All (selected), Savings, Loans, Shares, Goals
- Selected indicator pill below active tab
- Horizontal scroll if needed
Net Worth Hero Card:
- Full width, gradient #667EEA to #764BA2, 24dp radius
- "NET WORTH" label white 12sp + eye toggle
- "$18,450.00" balance 36sp white ExtraBold centered
- Two stat chips: "+$1,250 This Month" green, "-$380 Expenses" red
- Financial Health Score section: circular ring 85/100, "EXCELLENT" label
- "+5 from last month" change indicator
Spending Analytics Section:
- "SPENDING ANALYTICS" header + "This Week" dropdown
- "$1,240 spent" amount, "-12% vs last week" indicator green
- Bar chart 120dp height, 7 bars for Mon-Sun
- Today bar has dotted outline indicator
- Category chips horizontal scroll: Food $320 26%, Transport $180 15%, Shopping $450 36%, Bills $290 23%
AI Insights Section:
- "AI INSIGHTS" header + "See All" link
- Insight cards with gradient border 5% opacity
- Lightbulb icon, suggestion text, action buttons
- [Explore Options] [Dismiss]
Savings Accounts Section:
- "SAVINGS ACCOUNTS" header with count, total
- "7-day streak" flame badge, "+$850 this month"
- Account cards white 20dp radius, swipeable
- Primary Savings: wallet icon gradient bg, ****4521, $8,200.00
- Goal progress bar 65%, "$8,200 / $12,600"
- Gamification stats: fire streak, trophy goals, lightning auto-save
Loan Accounts Section:
- "LOAN ACCOUNTS" header with count, outstanding total
- "Debt-free in 18 months" projection
- Personal Loan card: -$4,500.00 red, 60% progress
- Next payment $350 due Jan 15, [Schedule] [Pay Now] buttons
Share Accounts Section:
- "SHARE ACCOUNTS" header with value
- "+$22.50 dividends this year"
- Community Shares: 15 shares @ $50, 3% APY
- [Buy More] [Sell Shares] buttons
Upcoming Bills Section:
- "DUE THIS WEEK" header + "Manage" link
- Overdue card: red left border 4dp, "OVERDUE" badge pulsing
- Electricity $85, "Was due Dec 28", [PAY NOW] [Snooze] buttons
- Due soon cards: amber indicator, Internet $65, Water $42, Rent $1,200
Bottom Navigation:
- 64dp height, 4 tabs: Home, Accounts (selected), FAB Transfer, Profile
- FAB 56dp gradient, elevated -16dp above nav bar
```
---
## Screen 2: Goals Tab View
```
Mobile goals dashboard screen, Material Design 3, fintech app, 393x852px
Tab Bar:
- Goals tab selected with indicator
Goals Overview Hero:
- Gradient card #667EEA to #764BA2
- "GOALS OVERVIEW" header
- Stats row: 4 Active, 2 Achieved, 1 Paused, $20,600 Total Goal
- Overall progress bar 62%, "$12,500 saved of $20,600 target"
Achievements Section:
- "ACHIEVEMENTS" header + "View All Badges" link
- Badge row horizontal: fire 7day, diamond $5k, target Goal Master, star Super Saver, lock ???
- States: EARNED (full color glow), 55% (grayscale + ring), LOCKED (grayscale)
Active Goals List:
- "ACTIVE GOALS" header + "+ Create Goal" button
- Emergency Fund card: shield emoji, 65% progress ring
- "$8,200 / $12,600", fire "7-day streak", "Est: Mar 2025"
- Auto-save info: "$50/week on Fridays", [Edit] [Pause] buttons
- Bali Trip card: palm emoji, 45% progress
- "$3,500 / $8,000", "Boost available!" callout
- [Boost Now] [Maybe Later] buttons
Achieved Goals Section:
- "ACHIEVED GOALS" header with celebration emoji
- New Laptop: checkmark, "$1,500 saved", "Completed Dec 2024"
- Holiday Shopping: checkmark, "$800 saved", "Completed Nov 2024"
```
---
## Screen 3: Spending Category Drill-Down
```
Mobile category detail screen, Material Design 3, fintech app, 393x852px
Top Bar:
- Back arrow, "Food & Dining" title, Share button
- "This Week" dropdown selector
Hero Stats:
- "$320.45 spent this week" large centered
- Line chart showing daily spending trend
- "15% vs last week" comparison
- "Budget: $400/week" with progress bar 80%
Sub-Categories Section:
- "SUB-CATEGORIES" header
- Restaurants $185 (58%) with progress bar
- Coffee & Cafes $68.50 (21%)
- Groceries $45.95 (14%)
- Fast Food $21.00 (7%)
Recent Transactions:
- "RECENT TRANSACTIONS" header + "See All" link
- Today section:
- Pizza Palace -$24.50, Restaurants, 2:30 PM, Visa ****4521
- Starbucks -$6.75, Coffee & Cafes, 9:15 AM
- Yesterday section:
- Whole Foods -$45.95, Groceries, 6:45 PM
- McDonald's -$12.50, Fast Food, 12:30 PM
AI Insight Card:
- Lightbulb icon, gradient border
- "You spent 58% on restaurants this week. Cooking at home 2 more days could save ~$50"
- [Set Cooking Goal] [Dismiss] buttons
```
---
## Screen 4: Loading State
```
Mobile accounts loading skeleton, Material Design 3, 393x852px
Tab Bar:
- Shimmer chips for filter tabs
Net Worth Hero Skeleton:
- Gradient background shape
- Shimmer placeholders: 200dp balance, two 80dp stat chips
- Shimmer health score circle
Analytics Skeleton:
- Header shimmer bar
- 7 shimmer bar chart shapes
- 4 category chip shimmers
Account Cards Skeleton:
- White card shapes with:
- 48dp icon circle shimmer
- Two text line shimmers (180dp, 120dp)
- Balance shimmer 80dp right aligned
Shimmer animation: left-to-right sweep, 1200ms infinite
Gradient: #E1E4E8#F8F9FA#E1E4E8
```
---
## Screen 5: Empty State
```
Mobile accounts empty state, Material Design 3, 393x852px
Header: Same as success with tabs visible
Center Content:
- Floating illustration 160dp: briefcase/portfolio icon
- Subtle up-down animation 2s loop
- "Start Your Financial Journey" title 20sp bold
- "Open your first account and take control of your finances" subtitle centered
Suggested Section:
- "SUGGESTED FOR YOU" header
- Savings Account card: bank icon, "4.5% APY", "Min: $0, No fees", [Open Now] button
- Investment Club card: chart icon, "3% dividends", "Min: 1 @ $50", [Learn More] button
CTA:
- "Explore All Account Types →" text link centered
```
---
## Screen 6: Error State
```
Mobile accounts error state, Material Design 3, 393x852px
Header: Same as success
Center Content:
- Cloud with X icon illustration, #FF4757 tint
- "Something Went Wrong" title 20sp bold
- "We couldn't load your accounts. Please check your connection."
Actions:
- "Try Again" gradient button full width
- "Check Network Settings" text link below
```
---
## Screen 7: Offline State
```
Mobile accounts offline banner, Material Design 3, 393x852px
Offline Banner:
- 48dp height, #FFB800 15% background
- Antenna icon, "You're offline" message, [Reconnect] button
Header:
- "My Accounts" title
- "Last updated 2 hours ago" subtitle gray
Content:
- All data at 70% opacity
- "(Cached)" labels on section headers
- Net Worth card with desaturated overlay
- "Data may be outdated" warning
Analytics Section:
- "Unavailable" badge
- Placeholder: "Data requires internet connection"
Account Cards:
- "Read-only mode • Cannot make transactions" banner
- Normal cards but swipe actions disabled
```
---
## Components
### Net Worth Hero Card
```
Financial summary hero card, Material Design 3:
- Width: 361dp, height ~220dp
- Gradient #667EEA to #764BA2, 24dp radius
- "NET WORTH" white 12sp + eye toggle
- Balance 36sp white ExtraBold centered
- Stat chips: semi-transparent white bg
- Financial Health Score: circular ring 80dp, score 36sp center
- Level 3 shadow, gradient glow at 20%
```
### Financial Health Score Ring
```
Circular score indicator, Material Design 3:
- Outer ring: 80dp diameter, 8dp stroke
- Track: white 20% opacity
- Fill: gradient based on score level
- Center: score number 36sp, rating label 12sp
- Animation: ring fills + counter animates on load
- Change indicator below: "+5 from last month"
```
### Spending Analytics Bar Chart
```
Weekly spending bar chart, Material Design 3:
- Height: 120dp
- 7 bars for Mon-Sun
- Bar width: 24dp, spacing: 12dp
- Bar color: primary gradient
- Today: dotted outline indicator
- Touch: tooltip with exact amount
- Animation: bars grow from bottom 400ms staggered
```
### AI Insight Card
```
AI suggestion card, Material Design 3:
- Width: 361dp, auto height
- Gradient border 1dp at 20% opacity
- Background: gradient at 5% opacity
- Lightbulb icon 24dp left
- Message text 14sp
- Action buttons: outlined style
- Swipe to dismiss
```
### Account Card (Enhanced)
```
Enhanced account card, Material Design 3:
- Width: 361dp, height ~140dp auto
- White surface, 20dp radius, 2dp elevation
- Left: 48dp icon container, gradient 15% bg
- Account name 16sp, number 12sp gray
- Balance 24sp bold, change indicator 14sp
- Goal section: emoji, name, progress bar, percentage
- Gamification row: streak, goals, auto-save chips
- Swipe actions: Deposit green, Details blue (left), Pay Now purple, Schedule orange (right for loans)
```
### Achievement Badge
```
Achievement badge component, Material Design 3:
- Size: 64dp × 80dp
- Icon container: 48dp circle
- Icon: 28dp emoji
- Label: 10sp below
- States: EARNED (full color + glow), PROGRESS (grayscale + ring %), LOCKED (grayscale + lock icon)
- Tap: reveals requirements for locked
```
---
## Quick Start
1. Open [stitch.withgoogle.com](https://stitch.withgoogle.com)
2. Create project "Mifos Mobile - Accounts"
3. Copy each screen prompt → Generate
4. Generate components separately for reuse
5. Export all to Figma when done

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

View File

@ -1,169 +0,0 @@
# Auth - API Reference
## Base URL
`https://tt.mifos.community/fineract-provider/api/v1/self/`
---
## Endpoints Required
### 1. User Login
**Endpoint**: `POST /authentication`
**Description**: Authenticate user with username and password
**Request**:
```json
{
"username": "string",
"password": "string"
}
```
**Response**:
```json
{
"userId": 123,
"username": "john_doe",
"clients": [456],
"isAuthenticated": true,
"base64EncodedAuthenticationKey": "encoded_key",
"officeName": "Head Office"
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class User(
val userId: Long,
val username: String?,
val clients: List<Long>,
val isAuthenticated: Boolean,
val base64EncodedAuthenticationKey: String?,
val officeName: String?,
)
```
**Status**: ✅ Implemented in AuthenticationService
---
### 2. User Registration
**Endpoint**: `POST /registration`
**Description**: Register a new user account
**Request**:
```json
{
"accountNumber": "string",
"authenticationMode": "email",
"email": "user@example.com",
"firstName": "John",
"middleName": "M",
"lastName": "Doe",
"mobileNumber": "1234567890",
"password": "securePassword123",
"username": "john_doe"
}
```
**Response**:
```json
{
"requestId": "12345"
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class RegisterPayload(
val accountNumber: String,
val authenticationMode: String = "email",
val email: String,
val firstName: String,
val middleName: String,
val lastName: String,
val mobileNumber: String,
val password: String,
val username: String,
)
```
**Status**: ✅ Implemented in RegistrationService
---
### 3. Verify OTP
**Endpoint**: `POST /registration/user`
**Description**: Verify user registration with OTP
**Request**:
```json
{
"authenticationToken": "123456",
"requestId": "12345"
}
```
**Response**:
```json
{
"message": "User verified successfully"
}
```
**Status**: ✅ Implemented in RegistrationService
---
### 4. Update Password
**Endpoint**: `PUT /user/password`
**Description**: Update user password
**Request**:
```json
{
"newPassword": "newSecurePassword123",
"confirmPassword": "newSecurePassword123"
}
```
**Response**:
```json
{
"message": "Password updated successfully"
}
```
**Status**: ✅ Implemented in UserAuthRepository
---
## API Summary
| Endpoint | Service | Repository | Status |
|----------|---------|------------|--------|
| /authentication | AuthenticationService | UserAuthRepository | ✅ |
| /registration | RegistrationService | UserAuthRepository | ✅ |
| /registration/user | RegistrationService | UserAuthRepository | ✅ |
| /user/password | - | UserAuthRepository | ✅ |
---
## Error Responses
| Status Code | Error | Description |
|-------------|-------|-------------|
| 400 | Bad Request | Invalid credentials or payload |
| 401 | Unauthorized | Authentication failed |
| 403 | Forbidden | Account locked or disabled |
| 500 | Server Error | Internal server error |

File diff suppressed because it is too large Load Diff

View File

@ -1,255 +0,0 @@
# Auth - Feature Specification
> **Purpose**: User authentication, registration, password recovery
> **User Value**: Secure access to banking services
> **Last Updated**: 2025-12-27
---
## 1. Overview
### 1.1 Feature Summary
The Auth feature provides comprehensive authentication flows including login, registration, OTP verification, password recovery, and ID document upload for new users.
### 1.2 User Stories
- As a user, I want to log in with my credentials so that I can access my accounts
- As a new user, I want to register an account so that I can use the banking app
- As a user, I want to recover my password if I forget it
---
## 2. Screen Layouts
### 2.1 Login Screen
```
┌─────────────────────────────────────────┐
│ │
│ [Mifos Logo] │
│ │
│ ┌─────────────────────────────────┐ │
│ │ Username │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ Password 👁 │ │
│ └─────────────────────────────────┘ │
│ │
│ Forgot Password? │
│ │
│ ┌─────────────────────────────────┐ │
│ │ SIGN IN │ │
│ └─────────────────────────────────┘ │
│ │
│ Don't have an account? Sign Up │
│ │
└─────────────────────────────────────────┘
```
### 2.2 Registration Screen
```
┌─────────────────────────────────────────┐
│ ← Back Register │
├─────────────────────────────────────────┤
│ │
│ First Name [________________] │
│ Middle Name [________________] │
│ Last Name [________________] │
│ Email [________________] │
│ Mobile Number [________________] │
│ Account Number [________________] │
│ Password [________________] │
│ [Password Strength Indicator] │
│ Confirm Password [________________] │
│ │
│ ┌─────────────────────────────────┐ │
│ │ REGISTER │ │
│ └─────────────────────────────────┘ │
│ │
│ Already have an account? Login │
│ │
└─────────────────────────────────────────┘
```
### 2.3 Sections Table
| # | Screen | Description | Priority |
|---|--------|-------------|----------|
| 1 | LoginScreen | Username/password login | P0 |
| 2 | RegistrationScreen | New user registration form | P0 |
| 3 | OtpAuthenticationScreen | OTP verification | P0 |
| 4 | RecoverPasswordScreen | Password recovery | P1 |
| 5 | SetPasswordScreen | Set new password | P1 |
| 6 | UploadIdScreen | ID document upload | P1 |
---
## 3. User Interactions
| Action | Trigger | Result | API Call |
|--------|---------|--------|----------|
| Login | Click Sign In | Validate & authenticate | POST /authentication |
| Register | Click Register | Submit registration | POST /registration |
| Verify OTP | Click Next | Verify user | POST /registration/user |
| Recover Password | Click Recover | Send recovery code | POST /user/password |
| Set Password | Click Submit | Update password | PUT /user/password |
---
## 4. State Model
```kotlin
// Login State
data class LoginState(
val username: String = "",
val password: String = "",
val isPasswordVisible: Boolean = false,
val clientName: String = "",
val isError: Boolean = false,
val userNameError: StringResource? = null,
val passwordError: StringResource? = null,
val dialogState: DialogState? = null,
val uiState: ScreenUiState?,
val showOverlay: Boolean = false,
) {
sealed interface DialogState {
data class Error(val message: String) : DialogState
}
val isLoginButtonEnabled: Boolean
get() = username.isNotEmpty() && password.length >= 8
}
// Login Events
sealed interface LoginEvent {
data object NavigateToSignup : LoginEvent
data object NavigateToPasscode : LoginEvent
data object NavigateToForgotPassword : LoginEvent
data class ShowToast(val message: String) : LoginEvent
}
// Login Actions
sealed interface LoginAction {
data class UsernameChanged(val username: String) : LoginAction
data class PasswordChanged(val password: String) : LoginAction
data object TogglePasswordVisibility : LoginAction
data object ErrorDialogDismiss : LoginAction
data object LoginClicked : LoginAction
data object SignupClicked : LoginAction
data object NavigateToForgotPassword : LoginAction
}
// Registration State
data class SignUpState(
val customerAccount: String = "",
val firstName: String = "",
val middleName: String = "",
val lastName: String = "",
val email: String = "",
val password: String = "",
val confirmPassword: String = "",
val mobileNumber: String = "",
val dialogState: SignUpDialog? = null,
val uiState: ScreenUiState = ScreenUiState.Success,
val showOverlay: Boolean = false,
val isPasswordChanged: Boolean = false,
val isPasswordVisible: Boolean = false,
val isConfirmPasswordVisible: Boolean = false,
val passwordFeedback: List<StringResource> = emptyList(),
val passwordStrengthState: PasswordStrengthState = PasswordStrengthState.NONE,
// Validation errors
val firstNameError: StringResource? = null,
val middleNameError: StringResource? = null,
val lastNameError: StringResource? = null,
val emailError: StringResource? = null,
val mobileNumberError: StringResource? = null,
val customerAccountError: StringResource? = null,
val passwordError: StringResource? = null,
val confirmPasswordError: StringResource? = null,
) {
sealed interface SignUpDialog {
data class Error(val message: String) : SignUpDialog
}
val isSubmitButtonEnabled: Boolean
get() = customerAccount.isNotBlank() &&
firstName.isNotBlank() &&
lastName.isNotBlank() &&
email.isNotBlank() &&
password.isNotBlank() &&
confirmPassword.isNotBlank()
}
// Registration Events
sealed interface SignUpEvent {
data class ShowToast(val message: String) : SignUpEvent
data object NavigateToUploadDocuments : SignUpEvent
data object NavigateToLogin : SignUpEvent
}
```
---
## 5. API Requirements
| Endpoint | Method | Purpose | Status |
|----------|--------|---------|--------|
| /self/authentication | POST | User login | ✅ Exists |
| /self/registration | POST | Register user | ✅ Exists |
| /self/registration/user | POST | Verify OTP | ✅ Exists |
| /self/user/password | PUT | Update password | ✅ Exists |
---
## 6. Validation Rules
| Field | Validation | Error Message |
|-------|------------|---------------|
| Username | Required, non-empty | "Enter username" |
| Password | Required, min 8 chars | "Password must be 8+ chars" |
| Email | Valid email format | "Invalid email format" |
| Phone | 10+ digits, numeric | "Invalid phone number" |
| Names | Letters only | "No special characters allowed" |
---
## 7. Password Strength
| Level | Score | Requirements |
|-------|-------|--------------|
| WEAK_1 | 0 | < 8 chars |
| WEAK_2 | 1 | 8 chars, no variety |
| WEAK_3 | 2 | 8 chars, some variety |
| GOOD | 3 | 8 chars, uppercase/lowercase |
| STRONG | 4 | 8 chars, includes numbers |
| VERY_STRONG | 5 | 8 chars, includes symbols |
---
## 8. Navigation Flow
```
AUTH_GRAPH (Start: LoginRoute)
├── LoginRoute
│ ├── → RegistrationRoute (Sign Up)
│ ├── → RecoverPasswordRoute (Forgot Password)
│ └── → PasscodeScreen (Login success)
├── RegistrationRoute
│ └── → UploadIdRoute → OtpAuthenticationRoute
├── OtpAuthenticationRoute
│ └── → StatusScreen (Success/Failure)
├── RecoverPasswordRoute
│ └── → OtpAuthenticationRoute → SetPasswordRoute
└── SetPasswordRoute
└── → StatusScreen → LoginRoute
```
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Updated state models to match actual implementation, added Events/Actions |
| 2025-12-27 | Initial spec from codebase analysis |

View File

@ -1,114 +0,0 @@
# Auth - Implementation Status
> **Last Updated**: 2025-12-29
> **Overall Status**: ✅ Done
---
## Implementation Checklist
- [x] SPEC.md created
- [x] API.md created
- [x] Network: Services exist
- [x] Data: Repository exists
- [x] Feature: ViewModel + Screen
- [x] Navigation: Route registered
- [x] DI: Modules registered
- [x] STATUS.md updated
---
## Layer Status
| Layer | Status | Files |
|-------|--------|-------|
| Network | ✅ | AuthenticationService.kt, RegistrationService.kt |
| Data | ✅ | UserAuthRepository.kt, UserAuthRepositoryImp.kt |
| Feature | ✅ | LoginViewModel, LoginScreen, RegistrationViewModel, RegistrationScreen, OtpAuthenticationViewModel, OtpAuthenticationScreen, RecoverPasswordViewModel, RecoverPasswordScreen, SetPasswordViewModel, SetPasswordScreen, UploadIdViewmodel, UploadIdScreen |
| DI | ✅ | AuthModule.kt |
| Navigation | ✅ | AuthenticationNavGraph.kt |
---
## Files
### Network Layer
The authentication feature uses two main services for API communication:
- **AuthenticationService.kt** - Handles user authentication requests (login, OTP verification)
- Location: `/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/`
- **RegistrationService.kt** - Manages user registration and account creation flows
- Location: `/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/`
### Data Layer
The data layer provides repository implementations that bridge network and UI layers:
- **UserAuthRepository.kt** - Interface defining authentication operations
- Location: `/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repository/`
- **UserAuthRepositoryImp.kt** - Implementation of UserAuthRepository
- Location: `/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/`
### Feature Layer
The feature module contains multiple authentication screens and their associated ViewModels:
**Login Flow:**
- **LoginViewModel.kt** - Manages login state and authentication logic
- **LoginScreen.kt** - Composable UI for user login
**Registration Flow:**
- **RegistrationViewModel.kt** - Handles user registration logic
- **RegistrationScreen.kt** - Composable UI for user registration
**OTP Authentication:**
- **OtpAuthenticationViewModel.kt** - Manages OTP verification state
- **OtpAuthenticationScreen.kt** - Composable UI for OTP input
**Password Recovery:**
- **RecoverPasswordViewModel.kt** - Handles password recovery flow
- **RecoverPasswordScreen.kt** - Composable UI for password recovery initiation
**Set New Password:**
- **SetPasswordViewModel.kt** - Manages new password setup
- **SetPasswordScreen.kt** - Composable UI for setting new password
**Document Upload:**
- **UploadIdViewmodel.kt** - Manages document upload state
- **UploadIdScreen.kt** - Composable UI for document upload
- **UploadDocumentsSection.kt** - Reusable component for document section
All files are located at: `/feature/auth/src/commonMain/kotlin/org/mifos/mobile/feature/auth/`
### Dependency Injection
- **AuthModule.kt** - Koin module defining all auth-related dependencies
- Location: `/feature/auth/src/commonMain/kotlin/org/mifos/mobile/feature/auth/di/`
### Navigation
- **AuthenticationNavGraph.kt** - Defines navigation graph and routes for auth feature
- Location: `/feature/auth/src/commonMain/kotlin/org/mifos/mobile/feature/auth/navigation/`
- Individual screen navigation files: LoginNavigation.kt, RegistrationNavigation.kt, UploadIdNavigation.kt, etc.
---
## Gaps
None identified. The authentication feature is fully implemented across all layers:
- Complete network service layer with API integration
- Full data persistence and repository pattern
- Comprehensive feature UI with multiple authentication screens
- Proper dependency injection configuration
- Navigation graph with all auth routes registered
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Initial status documentation |

View File

@ -1,76 +0,0 @@
# Auth - Figma Links
> **Feature**: Authentication Flow
> **Last Updated**: 2026-01-03
> **Status**: ⚠️ Flow diagram created, UI mockups pending
---
## User Flow Diagram (FigJam)
| Property | Value |
|----------|-------|
| **Diagram URL** | [Auth User Flow](https://www.figma.com/online-whiteboard/create-diagram/28749b96-55e0-4f0d-98b3-dabe150a3f5f?utm_source=chatgpt&utm_content=edit_in_figjam&oai_id=&request_id=e5358ddf-7de3-4e4a-9beb-e035f510673c) |
| **Type** | FigJam Flowchart |
| **Generated** | 2026-01-03 via Figma MCP |
---
## Main Figma File (UI Mockups)
| Property | Value |
|----------|-------|
| **File URL** | `(add after creating mockups)` |
| **Project** | Mifos Mobile v2.0 |
| **Page** | Auth Flow |
---
## Screen Links
| # | Screen | Frame Name | Figma URL | Status |
|:-:|--------|------------|-----------|:------:|
| 1 | Splash | auth/splash | `(pending)` | ⏳ |
| 2 | Welcome | auth/welcome | `(pending)` | ⏳ |
| 3 | Login Hub | auth/login-hub | `(pending)` | ⏳ |
| 4 | OTP Verify | auth/otp-verify | `(pending)` | ⏳ |
| 5 | Email Login | auth/email-login | `(pending)` | ⏳ |
| 6 | Biometric Setup | auth/biometric-setup | `(pending)` | ⏳ |
| 7 | Server Selection | auth/server-selection | `(pending)` | ⏳ |
| 8 | Success | auth/success | `(pending)` | ⏳ |
---
## Component Links
| Component | Frame Name | Figma URL | Status |
|-----------|------------|-----------|:------:|
| Primary Button | components/primary-button | `(pending)` | ⏳ |
| Text Input | components/text-input | `(pending)` | ⏳ |
| OTP Input | components/otp-input | `(pending)` | ⏳ |
| Auth Card | components/auth-card | `(pending)` | ⏳ |
---
## Export Checklist
- [ ] Generated all 8 screens in Google Stitch
- [ ] Exported to Figma
- [ ] Organized in pages/frames
- [ ] Updated URLs above
- [ ] Shared with team
---
## How to Update
1. Export designs from Google Stitch to Figma
2. Copy Figma frame URLs (right-click → Copy link)
3. Update the table above with URLs
4. Change status from ⏳ to ✅
---
## Notes
(Add any design notes or decisions here)

View File

@ -1,404 +0,0 @@
# Auth - AI Mockup Prompts
> **Generated from**: features/auth/MOCKUP.md
> **Generated on**: 2026-01-03
> **AI Tool**: Google Stitch (Material Design 3)
> **Design Style**: Premium Fintech (Revolut + Monzo inspired)
---
## Screen 1: Splash Screen
### Google Stitch Prompt
Create a mobile splash screen for a premium fintech banking app with Material Design 3:
**App Context:**
Mifos Mobile - Self-service banking app for managing accounts, loans, and transfers.
**Screen Size:** 393 x 852 pixels (Android standard)
**Background:**
- Full screen gradient at 45° angle
- Start color: #667EEA (Purple-Blue)
- End color: #764BA2 (Deep Purple)
**Center Content:**
- App logo: 72dp white icon, centered
- Logo has subtle glow effect (20dp blur, white 15% opacity)
- Below logo: "MIFOS" text, 24sp, white, letter-spacing 8dp
- Tagline: "Your Financial Freedom", 14sp, white 70% opacity
**Bottom:**
- Three loading dots, sequential pulse animation
- White color, 8dp diameter each
**Style Guidelines:**
- Premium, modern fintech aesthetic
- Smooth gradient transition
- Minimalist, trust-building design
- No visible UI chrome
---
## Screen 2: Welcome/Onboarding Screen
### Google Stitch Prompt
Create a mobile onboarding welcome screen for a fintech app with Material Design 3:
**App Context:**
Mifos Mobile - First-time user onboarding with value propositions.
**Screen Size:** 393 x 852 pixels
**Top Right:**
- "Skip" text link, 14sp, color #667EEA
**Center:**
- Large illustration area: 240dp x 240dp
- Animated illustration showing money/cards/transfers
- Use fintech iconography (credit cards, dollar signs, arrows)
**Below Illustration:**
- Title: "Manage Your Money", 28sp, Bold, #1F2937
- Subtitle: "Track spending, save smarter, and transfer money instantly—all in one secure app.", 16sp, #6B7280, center-aligned, line-height 24dp
**Page Indicators:**
- Three dots horizontally centered
- Active dot: #667EEA (filled)
- Inactive dots: #E5E7EB (outlined)
**Primary Button:**
- "Get Started" button, full width with 16dp horizontal margin
- Height: 56dp, Corner radius: 16dp
- Background: Gradient #667EEA#764BA2
- Text: 16sp, SemiBold, White
- Shadow: 0 4dp 12dp rgba(102,126,234,0.3)
**Below Button:**
- "Already have an account? Sign In", 14sp
- "Sign In" is a link in #667EEA
**Bottom:**
- Trust badge: "🔒 Bank-grade security • 256-bit encryption"
- 12sp, #9CA3AF, centered
---
## Screen 3: Login Hub Screen
### Google Stitch Prompt
Create a mobile login screen for a fintech banking app with Material Design 3:
**App Context:**
Mifos Mobile - Login screen with multiple authentication options.
**Screen Size:** 393 x 852 pixels
**Header:**
- Mifos logo centered, 56dp, primary gradient colors
- Title: "Welcome Back", 24sp, Bold, #1F2937
- Subtitle: "Sign in to continue", 14sp, #6B7280
**Phone Input Section:**
- Container with country picker and phone input
- Country picker: Flag + dial code (e.g., 🇺🇸 +1), dropdown arrow
- Phone input: "Enter phone number" placeholder
- Container height: 56dp, border: 1dp #E5E7EB, radius: 12dp
- Focus state: border 2dp #667EEA with shadow
**Primary Button:**
- "Continue with Phone", full width
- Same styling as onboarding button
- Disabled state until valid phone entered
**Divider:**
- "─────── or ───────" with "or" text
**Alternative Auth Cards:**
- Two side-by-side cards
- Left: "Use Biometric" with face icon
- Right: "Use Email" with email icon
- Each: 56dp height, outlined, 12dp radius
**Bottom Section:**
- Server info: "Server: gsoc.mifos.community [Change]"
- Trust badge: "🔒 256-bit encryption • Your data is secure"
---
## Screen 4: OTP Verification Screen
### Google Stitch Prompt
Create a mobile OTP verification screen for a fintech app with Material Design 3:
**App Context:**
Mifos Mobile - 6-digit SMS code verification after phone login.
**Screen Size:** 393 x 852 pixels
**Top:**
- Back arrow button, 24dp, #1F2937
**Center Icon:**
- Phone with checkmark illustration
- 80dp container with primary gradient background
- Animated scanning effect
**Title Section:**
- "Verify Your Phone", 24sp, Bold, #1F2937
- "We sent a 6-digit code to", 14sp, #6B7280
- "+1 (555) 123-4567", 14sp, Bold, #1F2937
**OTP Input:**
- 6 individual input boxes in a row
- Each box: 48dp x 56dp, gap: 12dp between
- Border: 2dp #E5E7EB, radius: 8dp
- Filled state: background #667EEA 10%, border #667EEA
- Numbers: 24sp, Bold, center-aligned
**Auto-read indicator:**
- "Auto-reading SMS..." with animated dots
- 12sp, #667EEA
**Resend Section:**
- "Didn't receive the code?", 14sp, #6B7280
- "Resend in 0:45" countdown, 14sp, #667EEA (disabled)
- After timer: "Resend Code" link, underlined
**Bottom:**
- "🔒 Code expires in 10 minutes", 12sp, #9CA3AF
---
## Screen 5: Email/Password Login Screen
### Google Stitch Prompt
Create a mobile email login screen for a fintech app with Material Design 3:
**App Context:**
Mifos Mobile - Alternative login for username/password users.
**Screen Size:** 393 x 852 pixels
**Top:**
- Back arrow button
- Mifos logo centered, smaller (48dp)
**Title:**
- "Sign in with Email", 24sp, Bold, #1F2937
**Form Fields:**
**Username/Email Input:**
- Label: "Username or Email", 12sp, #6B7280, floating
- Input: 56dp height, user icon (👤) left, 16sp text
- Border: 1dp #E5E7EB, radius: 12dp
- Focus: 2dp #667EEA border, shadow
**Password Input:**
- Label: "Password", 12sp, #6B7280
- Input: 56dp height, lock icon (🔒) left, visibility toggle (👁) right
- Password dots: ••••••••••••
**Forgot Password:**
- "Forgot Password?" link, right-aligned, 14sp, #667EEA
**Primary Button:**
- "Sign In", full width, gradient background
**Divider:**
- "─────── or ───────"
**Alternative Auth:**
- Two option cards: "Use Biometric" and "Use Phone"
**Bottom:**
- Server info row
- Security badge
---
## Screen 6: Biometric Setup Screen
### Google Stitch Prompt
Create a mobile biometric enrollment screen for a fintech app with Material Design 3:
**App Context:**
Mifos Mobile - Face ID/Fingerprint setup for quick login.
**Screen Size:** 393 x 852 pixels
**Top Right:**
- "Skip" text link
**Center Illustration:**
- Large face/fingerprint illustration, 200dp x 200dp
- Face ID variant: Face outline with scanning animation
- Primary gradient accent colors
- Animated scanning line effect
**Title:**
- "Enable Face ID" (or "Enable Fingerprint"), 24sp, Bold, #1F2937
**Description:**
- "Use Face ID for quick and secure access to your Mifos account."
- 16sp, #6B7280, center-aligned, max-width 280dp
**Primary Button:**
- "Enable Face ID", full width, gradient
**Secondary Button:**
- "Maybe Later", text button, 14sp, #6B7280
**Bottom Info:**
- " You can enable this anytime in Settings"
- 12sp, #9CA3AF
---
## Screen 7: Server Selection Screen
### Google Stitch Prompt
Create a mobile server selection screen for a fintech app with Material Design 3:
**App Context:**
Mifos Mobile - Allow users to switch between different Mifos instances.
**Screen Size:** 393 x 852 pixels
**Top:**
- Back button
- Title: "Select Server", 24sp, Bold, #1F2937
- Subtitle: "Choose your Mifos instance", 14sp, #6B7280
**Recommended Section:**
- Section label: "RECOMMENDED", 12sp, #6B7280
- Card with gradient border (selected state):
- Globe icon, "Demo Server", "gsoc.mifos.community"
- Checkmark indicator for selected
**Other Servers Section:**
- Section label: "OTHER SERVERS"
- Two outlined cards:
- Building icon, "Production Server", "demo.mifos.io"
- Wrench icon, "Sandbox Server", "sandbox.mifos.community"
**Custom Server Section:**
- Section label: "CUSTOM SERVER"
- Input field: "https://" with placeholder
- 56dp height, 12dp radius
**Primary Button:**
- "Connect", full width, gradient
---
## Screen 8: Login Success Screen
### Google Stitch Prompt
Create a mobile success/celebration screen for a fintech app with Material Design 3:
**App Context:**
Mifos Mobile - Celebration moment after successful login.
**Screen Size:** 393 x 852 pixels
**Center:**
- Large success animation, 160dp container
- Green checkmark (#00D09C) with confetti particles
- Confetti: multi-color small shapes bursting outward
**Title:**
- "You're All Set!", 28sp, Bold, #1F2937
**Welcome Message:**
- "Welcome back, Maria! 👋", 16sp, #6B7280
**Progress Indicator:**
- Linear progress bar at bottom
- "Setting up your dashboard...", 12sp, #6B7280
- Progress bar fills over 2.5 seconds
**Animation Notes:**
- Checkmark draws in with stroke animation
- Confetti bursts from center
- Auto-navigates to home after progress completes
---
## Component Prompts
### Primary Button Component
Create a Material Design 3 primary button for fintech app:
- Height: 56dp, Corner radius: 16dp
- Background: Linear gradient #667EEA#764BA2
- Text: 16sp, SemiBold, White, centered
- Shadow: 0 4dp 12dp rgba(102,126,234,0.3)
- Press state: scale to 0.98, reduce shadow
- Disabled: 50% opacity, no shadow
### Input Field Component
Create a Material Design 3 input field for fintech app:
- Height: 56dp, Corner radius: 12dp
- Border: 1dp #E5E7EB (default), 2dp #667EEA (focus)
- Left icon: 20dp, #9CA3AF (default), #667EEA (focus)
- Text: 16sp, #1F2937
- Placeholder: 16sp, #9CA3AF
- Focus shadow: 0 0 8dp rgba(102,126,234,0.2)
- Error: border #FF4757, icon #FF4757
### OTP Input Component
Create a Material Design 3 OTP input for fintech app:
- 6 boxes in a row, each 48dp x 56dp
- Gap: 12dp between boxes
- Border: 2dp #E5E7EB, radius: 8dp
- Filled: background #667EEA 10%, border #667EEA
- Focus: border #667EEA with glow
- Number: 24sp, Bold, centered
---
## Export Instructions
### Using Google Stitch
1. Go to [stitch.withgoogle.com](https://stitch.withgoogle.com/)
2. Sign in with Google account
3. Create new project "Mifos Mobile - Auth"
4. For each screen:
- Copy the prompt above
- Paste into Stitch
- Generate design
- Adjust as needed
5. Export all screens to Figma
### Export to Figma
1. In Stitch, click "Export to Figma"
2. Select your Figma team/project
3. Organize in pages:
- Page 1: Splash
- Page 2: Welcome
- Page 3: Login Hub
- Page 4: OTP
- Page 5: Email Login
- Page 6: Biometric Setup
- Page 7: Server Selection
- Page 8: Success
### After Export
Update `features/auth/mockups/FIGMA_LINKS.md` with:
- Figma file URL
- Individual frame URLs for each screen

View File

@ -1,206 +0,0 @@
# Auth - Figma First Draft Prompts
> **Tool**: Figma First Draft (Shift+I in Figma)
> **Style**: Premium Fintech, Modern Banking App
> **Format**: Natural language prompts optimized for Figma AI
---
## How to Use
1. Open Figma → Create new design file
2. Press `Shift + I` or click "Actions" → "First Draft"
3. Copy each prompt below
4. Generate → Iterate → Refine
---
## Screen 1: Splash Screen
```
Design a premium fintech app splash screen for "Mifos Mobile" banking app.
Use a beautiful purple-blue gradient background going diagonally. Place a white minimalist logo in the center with a subtle glow effect. Below the logo, show "MIFOS" in white uppercase letters with wide letter spacing. Add a tagline "Your Financial Freedom" in lighter white below.
At the bottom, show three small loading dots that would animate. Keep it clean, premium, and trustworthy like Revolut or Monzo splash screens. No navigation bars or buttons - just the brand moment.
```
---
## Screen 2: Welcome/Onboarding
```
Design a mobile onboarding welcome screen for a banking app.
At the top right, add a "Skip" text link in purple. In the center, create space for a friendly illustration showing money management - cards, coins, or transfer arrows.
Below the illustration, add a bold headline "Manage Your Money" and a subtitle explaining "Track spending, save smarter, and transfer money instantly—all in one secure app."
Show three page indicator dots (first one active in purple). Add a large "Get Started" button with a purple gradient background. Below it, show "Already have an account? Sign In" with Sign In as a clickable link.
At the very bottom, add a small trust badge showing "Bank-grade security • 256-bit encryption" with a lock icon.
```
---
## Screen 3: Login Hub
```
Design a modern login screen for a fintech app with multiple sign-in options.
Show the Mifos logo at the top, followed by "Welcome Back" as the main heading and "Sign in to continue" as a subtitle.
Create a phone number input field with a country code picker (showing a flag and +1). The input should have a clean outlined style.
Add a prominent "Continue with Phone" button with purple gradient.
Below, show a divider with "or" text.
Then display two side-by-side option cards: one for "Use Biometric" with a face icon, and one for "Use Email" with an email icon. Both should be outlined cards.
At the bottom, show server info "Server: gsoc.mifos.community" with a Change link, and a security badge about encryption.
```
---
## Screen 4: OTP Verification
```
Design an OTP code verification screen for a banking app.
Add a back arrow at the top left. Show a phone icon with a checkmark in a circular purple gradient container.
Display "Verify Your Phone" as the heading. Below it show "We sent a 6-digit code to" and the phone number "+1 (555) 123-4567" in bold.
Create 6 individual square input boxes for the OTP code, arranged in a row with small gaps between them. Some boxes should show numbers to indicate the filled state.
Show "Auto-reading SMS..." text in purple below the inputs.
Add a resend section: "Didn't receive the code?" with a "Resend in 0:45" countdown timer.
At the bottom, show "Code expires in 10 minutes" with a lock icon.
```
---
## Screen 5: Email/Password Login
```
Design an email and password login screen for a banking app.
Add a back arrow and the Mifos logo at the top. Show "Sign in with Email" as the heading.
Create two input fields:
1. Username or Email field with a user icon on the left
2. Password field with a lock icon on the left and an eye icon on the right to toggle visibility
Add a "Forgot Password?" link aligned to the right below the password field.
Include a "Sign In" button with purple gradient.
Show a divider with "or" text.
Add two alternative login options as outlined cards: "Use Biometric" and "Use Phone".
At the bottom, show server information and a security badge.
```
---
## Screen 6: Biometric Setup
```
Design a biometric authentication setup screen for a banking app.
Add a "Skip" link at the top right.
In the center, show a large illustration of Face ID or fingerprint scanning - make it look modern with scanning lines and purple accent colors.
Display "Enable Face ID" as the heading and explain "Use Face ID for quick and secure access to your Mifos account" as a centered paragraph below.
Add a primary "Enable Face ID" button with purple gradient.
Below it, add a "Maybe Later" text button in gray.
At the bottom, show a helpful note: "You can enable this anytime in Settings" with an info icon.
```
---
## Screen 7: Server Selection
```
Design a server selection screen for a banking app that connects to different backend servers.
Add a back arrow and "Select Server" as the title with "Choose your Mifos instance" as subtitle.
Create three sections:
RECOMMENDED section:
- A selected card with gradient border showing "Demo Server" and "gsoc.mifos.community" with a globe icon and checkmark
OTHER SERVERS section:
- Card for "Production Server" at "demo.mifos.io" with a building icon
- Card for "Sandbox Server" at "sandbox.mifos.community" with a wrench icon
CUSTOM SERVER section:
- An input field with "https://" placeholder for entering a custom URL
Add a "Connect" button with purple gradient at the bottom.
```
---
## Screen 8: Login Success
```
Design a celebration/success screen shown after successful login to a banking app.
In the center, show a large green checkmark icon with confetti particles bursting around it - make it feel celebratory and delightful.
Display "You're All Set!" as a bold heading.
Below, show a personalized welcome message "Welcome back, Maria!" with a wave emoji.
At the bottom, add a progress bar that's filling up with text "Setting up your dashboard..." below it. This indicates the app is loading the home screen.
Keep it joyful but professional - like a premium banking app celebrating a successful login.
```
---
## Component Prompts
### Primary Button
```
Design a primary action button for a fintech app. Make it 56 pixels tall with rounded corners (16px radius). Use a purple gradient background from #667EEA to #764BA2. White text, medium weight, centered. Add a subtle shadow for depth. Show default, pressed, and disabled states.
```
### Text Input Field
```
Design a text input field for a banking app. 56 pixels tall with 12px rounded corners. Light gray border that turns purple when focused. Include a left icon area and right icon area (for things like visibility toggle). Show default, focused, filled, and error states.
```
### OTP Input
```
Design a 6-digit OTP code input for a banking app. Create 6 individual square boxes arranged horizontally with small gaps. Each box should have rounded corners and a light border. When filled, the box should have a light purple background. Numbers should be large and bold. Show empty, focused, and filled states.
```
---
## Tips for Figma First Draft
1. **Iterate**: First generation is a starting point - refine with follow-up prompts
2. **Be specific**: Add details about colors, spacing, and interactions
3. **Reference styles**: Mention "like Revolut" or "Monzo-style" for context
4. **Component mode**: Generate components separately, then assemble screens
5. **Variants**: Ask for multiple states (default, hover, pressed, disabled)
---
## After Generation
1. Review and adjust generated designs
2. Ensure consistency across all 8 screens
3. Create a component library from repeated elements
4. Export frames and update `FIGMA_LINKS.md`

View File

@ -1,266 +0,0 @@
# Auth - Google Stitch Prompts
> **Tool**: [Google Stitch](https://stitch.withgoogle.com)
> **Style**: Material Design 3, Premium Fintech
> **Format**: Copy each prompt block directly into Stitch
---
## Design System Reference
```
Primary Gradient: #667EEA#764BA2
Success: #00D09C
Error: #FF4757
Text Primary: #1F2937
Text Secondary: #6B7280
Text Muted: #9CA3AF
Border: #E5E7EB
Screen Size: 393 x 852 pixels (Android)
```
---
## Screen 1: Splash
```
Mobile splash screen, Material Design 3, fintech banking app, 393x852px
Background: Full gradient 45deg from #667EEA to #764BA2
Center:
- White app logo icon, 72dp, subtle glow effect
- "MIFOS" text below, 24sp white, letter-spacing 8dp
- Tagline "Your Financial Freedom", 14sp, white 70% opacity
Bottom: Three white loading dots, 8dp each, pulse animation
Style: Premium, minimalist, no UI chrome
```
---
## Screen 2: Welcome/Onboarding
```
Mobile onboarding screen, Material Design 3, fintech app, 393x852px
Top right: "Skip" link, 14sp, #667EEA
Center:
- Illustration 240x240dp showing money, cards, transfers
- Title "Manage Your Money", 28sp bold, #1F2937
- Subtitle "Track spending, save smarter, and transfer money instantly—all in one secure app", 16sp, #6B7280, centered
Page indicators: 3 dots, active #667EEA filled, inactive #E5E7EB outlined
Primary button: "Get Started", full width, 56dp height, 16dp radius, gradient #667EEA to #764BA2, white text, shadow
Below button: "Already have an account? Sign In" with "Sign In" as #667EEA link
Bottom: Lock icon + "Bank-grade security | 256-bit encryption", 12sp, #9CA3AF
```
---
## Screen 3: Login Hub
```
Mobile login screen, Material Design 3, fintech banking app, 393x852px
Header:
- Mifos logo centered, 56dp, gradient colors
- "Welcome Back", 24sp bold, #1F2937
- "Sign in to continue", 14sp, #6B7280
Phone input section:
- Country picker with flag + dial code dropdown
- Phone number input field
- Container 56dp height, 1dp #E5E7EB border, 12dp radius
Primary button: "Continue with Phone", full width, gradient, disabled until valid input
Divider: "or" with lines
Two side-by-side cards below:
- Left: Face icon + "Use Biometric", outlined, 56dp, 12dp radius
- Right: Email icon + "Use Email", outlined, 56dp, 12dp radius
Bottom:
- "Server: gsoc.mifos.community [Change]", small text
- Lock icon + "256-bit encryption | Your data is secure"
```
---
## Screen 4: OTP Verification
```
Mobile OTP verification screen, Material Design 3, fintech app, 393x852px
Top: Back arrow button, 24dp, #1F2937
Center icon: Phone with checkmark, 80dp container, gradient background
Title section:
- "Verify Your Phone", 24sp bold, #1F2937
- "We sent a 6-digit code to", 14sp, #6B7280
- "+1 (555) 123-4567", 14sp bold, #1F2937
OTP input: 6 individual boxes in row, each 48x56dp, 12dp gap, 2dp #E5E7EB border, 8dp radius
- Filled state: #667EEA 10% background, #667EEA border
- Numbers: 24sp bold centered
Below OTP: "Auto-reading SMS..." with dots, 12sp, #667EEA
Resend section:
- "Didn't receive the code?", 14sp, #6B7280
- "Resend in 0:45" countdown or "Resend Code" link
Bottom: Lock icon + "Code expires in 10 minutes", 12sp, #9CA3AF
```
---
## Screen 5: Email Login
```
Mobile email login screen, Material Design 3, fintech app, 393x852px
Top: Back arrow + Mifos logo centered 48dp
Title: "Sign in with Email", 24sp bold, #1F2937
Form fields:
1. Username/Email input
- Floating label "Username or Email", 12sp, #6B7280
- User icon left, 56dp height, 1dp #E5E7EB border, 12dp radius
2. Password input
- Floating label "Password"
- Lock icon left, eye toggle right
- Password dots shown
"Forgot Password?" link, right-aligned, 14sp, #667EEA
Primary button: "Sign In", full width, gradient
Divider: "or" with lines
Two option cards: "Use Biometric" and "Use Phone"
Bottom: Server info + security badge
```
---
## Screen 6: Biometric Setup
```
Mobile biometric setup screen, Material Design 3, fintech app, 393x852px
Top right: "Skip" link
Center:
- Large face/fingerprint illustration, 200x200dp
- Scanning animation effect
- Primary gradient accent colors
Title: "Enable Face ID", 24sp bold, #1F2937
Description: "Use Face ID for quick and secure access to your Mifos account", 16sp, #6B7280, centered, max 280dp width
Primary button: "Enable Face ID", full width, gradient
Secondary: "Maybe Later", text button, 14sp, #6B7280
Bottom: Info icon + "You can enable this anytime in Settings", 12sp, #9CA3AF
```
---
## Screen 7: Server Selection
```
Mobile server selection screen, Material Design 3, fintech app, 393x852px
Top: Back button + "Select Server" title 24sp bold + "Choose your Mifos instance" subtitle 14sp #6B7280
Section "RECOMMENDED" (12sp label):
- Card with gradient border (selected):
- Globe icon, "Demo Server", "gsoc.mifos.community"
- Checkmark for selected state
Section "OTHER SERVERS":
- Card: Building icon, "Production Server", "demo.mifos.io"
- Card: Wrench icon, "Sandbox Server", "sandbox.mifos.community"
Section "CUSTOM SERVER":
- Input field with "https://" prefix, 56dp, 12dp radius
Primary button: "Connect", full width, gradient
```
---
## Screen 8: Login Success
```
Mobile success celebration screen, Material Design 3, fintech app, 393x852px
Center:
- Large success animation container, 160dp
- Green checkmark (#00D09C) with confetti particles
- Multi-color confetti bursting outward
Title: "You're All Set!", 28sp bold, #1F2937
Welcome: "Welcome back, Maria!", 16sp, #6B7280
Bottom:
- Linear progress bar filling
- "Setting up your dashboard...", 12sp, #6B7280
```
---
## Components (Generate Separately)
### Primary Button
```
Material Design 3 button component:
- 56dp height, 16dp corner radius
- Gradient background #667EEA to #764BA2
- White text, 16sp semibold, centered
- Shadow: 0 4dp 12dp rgba(102,126,234,0.3)
- States: default, pressed (0.98 scale), disabled (50% opacity)
```
### Input Field
```
Material Design 3 input field:
- 56dp height, 12dp corner radius
- Border: 1dp #E5E7EB default, 2dp #667EEA focus
- Left icon 20dp, #9CA3AF default, #667EEA focus
- Text 16sp #1F2937, placeholder #9CA3AF
- Error state: #FF4757 border and icon
```
### OTP Input
```
Material Design 3 OTP input, 6 boxes:
- Each box 48x56dp, 12dp gap between
- Border 2dp #E5E7EB, 8dp radius
- Filled: #667EEA 10% background, #667EEA border
- Number: 24sp bold centered
```
---
## Quick Start
1. Open [stitch.withgoogle.com](https://stitch.withgoogle.com)
2. Create project "Mifos Mobile - Auth"
3. Copy each prompt block above
4. Generate screen → Adjust → Next screen
5. Export all to Figma when done

View File

@ -1,286 +0,0 @@
{
"feature": "auth",
"generated": "2026-01-03",
"tool": "google-stitch",
"version": "2.0",
"tokens": {
"colors": {
"primary": {
"gradient": {
"start": "#667EEA",
"end": "#764BA2",
"angle": 45
},
"solid": "#667EEA"
},
"secondary": {
"gradient": {
"start": "#11998E",
"end": "#38EF7D"
}
},
"surface": {
"light": "#FFFFFF",
"dark": "#0D1117"
},
"background": {
"light": "#FFFFFF",
"dark": "#0D1117"
},
"card": {
"light": "#FFFFFF",
"dark": "#21262D"
},
"text": {
"primary": {
"light": "#1F2937",
"dark": "#F0F6FC"
},
"secondary": {
"light": "#6B7280",
"dark": "#8B949E"
},
"placeholder": {
"light": "#9CA3AF",
"dark": "#6E7681"
}
},
"border": {
"default": {
"light": "#E5E7EB",
"dark": "#30363D"
},
"focus": "#667EEA"
},
"semantic": {
"success": "#00D09C",
"error": "#FF4757",
"warning": "#FFB800",
"info": "#667EEA"
}
},
"typography": {
"fontFamily": "Inter, system-ui, sans-serif",
"display": {
"size": "36sp",
"weight": "800",
"lineHeight": "44dp"
},
"headline": {
"large": {
"size": "28sp",
"weight": "700",
"lineHeight": "36dp"
},
"medium": {
"size": "24sp",
"weight": "700",
"lineHeight": "32dp"
}
},
"title": {
"large": {
"size": "20sp",
"weight": "600",
"lineHeight": "28dp"
},
"medium": {
"size": "16sp",
"weight": "600",
"lineHeight": "24dp"
}
},
"body": {
"large": {
"size": "16sp",
"weight": "400",
"lineHeight": "24dp"
},
"medium": {
"size": "14sp",
"weight": "400",
"lineHeight": "20dp"
}
},
"label": {
"large": {
"size": "14sp",
"weight": "500",
"lineHeight": "20dp"
},
"medium": {
"size": "12sp",
"weight": "500",
"lineHeight": "16dp"
}
}
},
"spacing": {
"xs": "4dp",
"sm": "8dp",
"md": "12dp",
"lg": "16dp",
"xl": "20dp",
"xxl": "24dp",
"xxxl": "32dp"
},
"radius": {
"sm": "8dp",
"md": "12dp",
"lg": "16dp",
"xl": "24dp",
"full": "9999dp"
},
"shadow": {
"button": {
"offsetY": "4dp",
"blur": "12dp",
"color": "rgba(102, 126, 234, 0.3)"
},
"card": {
"offsetY": "2dp",
"blur": "8dp",
"color": "rgba(0, 0, 0, 0.08)"
},
"focus": {
"blur": "8dp",
"color": "rgba(102, 126, 234, 0.2)"
}
}
},
"screens": [
{
"id": "splash",
"name": "Splash Screen",
"description": "Brand introduction with premium animation",
"components": ["logo", "loading-dots"]
},
{
"id": "welcome",
"name": "Welcome/Onboarding Screen",
"description": "First-time user value propositions carousel",
"components": ["illustration", "page-indicators", "primary-button", "text-link", "trust-badge"]
},
{
"id": "login-hub",
"name": "Login Hub Screen",
"description": "Multiple authentication options",
"components": ["logo", "phone-input", "country-picker", "primary-button", "divider", "auth-card", "server-info", "trust-badge"]
},
{
"id": "otp-verify",
"name": "OTP Verification Screen",
"description": "6-digit code verification",
"components": ["back-button", "icon-header", "otp-input", "countdown-timer", "text-link"]
},
{
"id": "email-login",
"name": "Email/Password Login Screen",
"description": "Alternative username/password login",
"components": ["back-button", "logo", "text-input", "password-input", "primary-button", "auth-card"]
},
{
"id": "biometric-setup",
"name": "Biometric Setup Screen",
"description": "Face ID/Fingerprint enrollment",
"components": ["skip-link", "illustration", "primary-button", "text-button", "info-badge"]
},
{
"id": "server-selection",
"name": "Server Selection Screen",
"description": "Instance switching for deployments",
"components": ["back-button", "server-card", "text-input", "primary-button"]
},
{
"id": "success",
"name": "Login Success Screen",
"description": "Celebration moment before home",
"components": ["success-animation", "progress-bar"]
}
],
"components": [
{
"id": "primary-button",
"name": "Primary Button",
"specs": {
"height": "56dp",
"radius": "16dp",
"background": "gradient",
"textSize": "16sp",
"textWeight": "600",
"textColor": "#FFFFFF",
"shadow": "button"
}
},
{
"id": "text-input",
"name": "Text Input Field",
"specs": {
"height": "56dp",
"radius": "12dp",
"border": "1dp",
"borderColor": "#E5E7EB",
"focusBorder": "2dp #667EEA",
"iconSize": "20dp",
"textSize": "16sp"
}
},
{
"id": "otp-input",
"name": "OTP Input Box",
"specs": {
"width": "48dp",
"height": "56dp",
"gap": "12dp",
"radius": "8dp",
"border": "2dp",
"textSize": "24sp",
"textWeight": "700"
}
},
{
"id": "auth-card",
"name": "Authentication Option Card",
"specs": {
"height": "56dp",
"radius": "12dp",
"border": "1dp #E5E7EB",
"iconSize": "24dp",
"textSize": "14sp"
}
},
{
"id": "trust-badge",
"name": "Trust/Security Badge",
"specs": {
"textSize": "12sp",
"textColor": "#9CA3AF",
"iconSize": "14dp"
}
}
],
"animations": {
"pageTransition": {
"type": "slide",
"duration": "300ms",
"easing": "FastOutSlowIn"
},
"buttonPress": {
"scale": "0.98",
"duration": "100ms"
},
"inputFocus": {
"duration": "200ms",
"easing": "ease"
},
"successCelebration": {
"checkmarkDraw": "300ms",
"confettiBurst": "600ms",
"haptic": "success"
},
"errorShake": {
"translateX": "[-10, 10, -5, 5, 0]",
"duration": "300ms"
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

View File

@ -1,585 +0,0 @@
# Beneficiary - API Reference
> **Base URL**: `https://tt.mifos.community/fineract-provider/api/v1/self/`
> **Authentication**: Basic Auth with `Fineract-Platform-TenantId` header
> **Last Updated**: 2025-12-29
---
## Authentication Headers
All endpoints require:
```
Headers:
Authorization: Basic {base64EncodedAuthenticationKey}
Fineract-Platform-TenantId: {tenantId}
Content-Type: application/json
```
---
## 1. Get Beneficiary List
### GET /self/beneficiaries/tpt
**Purpose**: Fetch all third-party transfer beneficiaries for the authenticated user
**Request**:
```
GET /self/beneficiaries/tpt
```
**Response**:
```json
[
{
"id": 5001,
"name": "John Doe",
"officeName": "Head Office",
"clientName": "John Doe",
"accountType": {
"id": 2,
"code": "accountType.savings",
"value": "Savings Account"
},
"accountNumber": "SA-0001234567",
"transferLimit": 10000.00
},
{
"id": 5002,
"name": "Jane Smith",
"officeName": "Branch Office",
"clientName": "Jane Smith",
"accountType": {
"id": 1,
"code": "accountType.loan",
"value": "Loan Account"
},
"accountNumber": "LA-0009876543",
"transferLimit": 5000.00
}
]
```
**Kotlin DTO**:
```kotlin
@Serializable
@Parcelize
data class Beneficiary(
val id: Long? = null,
val name: String? = null,
val officeName: String? = null,
val clientName: String? = null,
val accountType: AccountType? = null,
val accountNumber: String? = null,
val transferLimit: Double? = null,
) : Parcelable
```
**Status**: Implemented in `BeneficiaryService.beneficiaryList()`
---
## 2. Get Beneficiary Template
### GET /self/beneficiaries/tpt/template
**Purpose**: Fetch account type options for beneficiary creation form
**Request**:
```
GET /self/beneficiaries/tpt/template
```
**Response**:
```json
{
"accountTypeOptions": [
{
"id": 0,
"code": "accountType.share",
"value": "Share Account"
},
{
"id": 1,
"code": "accountType.loan",
"value": "Loan Account"
},
{
"id": 2,
"code": "accountType.savings",
"value": "Savings Account"
}
]
}
```
**Kotlin DTO**:
```kotlin
@Serializable
@Parcelize
data class BeneficiaryTemplate(
val accountTypeOptions: List<AccountTypeOption>? = null,
) : Parcelable
@Serializable
@Parcelize
data class AccountTypeOption(
val id: Int? = null,
val code: String? = null,
val value: String? = null,
) : Parcelable
```
**Status**: Implemented in `BeneficiaryService.beneficiaryTemplate()`
---
## 3. Create Beneficiary
### POST /self/beneficiaries/tpt
**Purpose**: Create a new third-party transfer beneficiary
**Request**:
```json
POST /self/beneficiaries/tpt
{
"locale": "en",
"name": "John Doe",
"accountNumber": "SA-0001234567",
"accountType": 2,
"transferLimit": 10000,
"officeName": "Head Office"
}
```
**Request Payload DTO**:
```kotlin
@Serializable
@Parcelize
data class BeneficiaryPayload(
val locale: String? = null,
val name: String? = null,
val accountNumber: String? = null,
val accountType: Int? = 0,
val transferLimit: Int? = 0,
val officeName: String? = null,
) : Parcelable
```
**Request Fields**:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| locale | String | Yes | Locale for the request (e.g., "en") |
| name | String | Yes | Beneficiary's display name |
| accountNumber | String | Yes | Target account number |
| accountType | Int | Yes | Account type ID (0=Share, 1=Loan, 2=Savings) |
| transferLimit | Int | Yes | Maximum transfer amount allowed |
| officeName | String | Yes | Office name where the account is held |
**Response (Success)**:
```json
{
"resourceId": 5003
}
```
**Response (Error)**:
```json
{
"developerMessage": "The account number does not exist",
"httpStatusCode": "400",
"defaultUserMessage": "Account not found",
"userMessageGlobalisationCode": "error.msg.beneficiary.account.not.found",
"errors": []
}
```
**Status**: Implemented in `BeneficiaryService.createBeneficiary()`
---
## 4. Update Beneficiary
### PUT /self/beneficiaries/tpt/{beneficiaryId}
**Purpose**: Update an existing beneficiary's name and transfer limit
**Request**:
```json
PUT /self/beneficiaries/tpt/5001
{
"name": "John Doe Updated",
"transferLimit": 15000
}
```
**Request Payload DTO**:
```kotlin
@Serializable
data class BeneficiaryUpdatePayload(
val name: String? = null,
val transferLimit: Int = 0,
)
```
**Request Fields**:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | String | Yes | Updated beneficiary name |
| transferLimit | Int | Yes | Updated transfer limit |
**Note**: Account number, account type, and office name cannot be updated. Only name and transfer limit can be modified.
**Response (Success)**:
```json
{
"resourceId": 5001,
"changes": {
"name": "John Doe Updated",
"transferLimit": 15000
}
}
```
**Response (Error)**:
```json
{
"developerMessage": "Beneficiary not found with id: 9999",
"httpStatusCode": "404",
"defaultUserMessage": "Beneficiary not found",
"userMessageGlobalisationCode": "error.msg.beneficiary.id.invalid",
"errors": []
}
```
**Status**: Implemented in `BeneficiaryService.updateBeneficiary()`
---
## 5. Delete Beneficiary
### DELETE /self/beneficiaries/tpt/{beneficiaryId}
**Purpose**: Delete an existing beneficiary
**Request**:
```
DELETE /self/beneficiaries/tpt/5001
```
**Response (Success)**:
```json
{
"resourceId": 5001
}
```
**Response (Error)**:
```json
{
"developerMessage": "Beneficiary not found with id: 9999",
"httpStatusCode": "404",
"defaultUserMessage": "Beneficiary not found",
"userMessageGlobalisationCode": "error.msg.beneficiary.id.invalid",
"errors": []
}
```
**Status**: Implemented in `BeneficiaryService.deleteBeneficiary()`
---
## Kotlin Service Interface
```kotlin
interface BeneficiaryService {
@GET(ApiEndPoints.BENEFICIARIES + "/tpt")
fun beneficiaryList(): Flow<List<Beneficiary>>
@GET(ApiEndPoints.BENEFICIARIES + "/tpt/template")
fun beneficiaryTemplate(): Flow<BeneficiaryTemplate>
@POST(ApiEndPoints.BENEFICIARIES + "/tpt")
suspend fun createBeneficiary(@Body beneficiaryPayload: BeneficiaryPayload?): HttpResponse
@PUT(ApiEndPoints.BENEFICIARIES + "/tpt/{beneficiaryId}")
suspend fun updateBeneficiary(
@Path("beneficiaryId") beneficiaryId: Long,
@Body payload: BeneficiaryUpdatePayload?,
): HttpResponse
@DELETE(ApiEndPoints.BENEFICIARIES + "/tpt/{beneficiaryId}")
suspend fun deleteBeneficiary(@Path("beneficiaryId") beneficiaryId: Long): HttpResponse
}
```
---
## Kotlin Repository Interface
```kotlin
interface BeneficiaryRepository {
fun beneficiaryTemplate(): Flow<DataState<BeneficiaryTemplate>>
suspend fun createBeneficiary(beneficiaryPayload: BeneficiaryPayload?): DataState<String>
suspend fun updateBeneficiary(
beneficiaryId: Long?,
payload: BeneficiaryUpdatePayload?,
): DataState<String>
suspend fun deleteBeneficiary(beneficiaryId: Long?): DataState<String>
fun beneficiaryList(): Flow<DataState<List<Beneficiary>>>
}
```
---
## Kotlin Repository Implementation
```kotlin
class BeneficiaryRepositoryImp(
private val dataManager: DataManager,
private val ioDispatcher: CoroutineDispatcher,
) : BeneficiaryRepository {
override fun beneficiaryTemplate(): Flow<DataState<BeneficiaryTemplate>> = flow {
try {
dataManager.beneficiaryApi.beneficiaryTemplate()
.collect { response ->
emit(DataState.Success(response))
}
} catch (exception: Exception) {
emit(DataState.Error(exception))
}
}.flowOn(ioDispatcher)
override suspend fun createBeneficiary(beneficiaryPayload: BeneficiaryPayload?): DataState<String> {
return withContext(ioDispatcher) {
try {
val response = dataManager.beneficiaryApi.createBeneficiary(beneficiaryPayload)
DataState.Success(response.bodyAsText())
} catch (e: ClientRequestException) {
val errorMessage = extractErrorMessage(e.response)
DataState.Error(Exception(errorMessage), null)
} catch (e: IOException) {
DataState.Error(Exception("Network error: ${e.message ?: "Please check your connection"}"), null)
} catch (e: ServerResponseException) {
DataState.Error(Exception("Server error: ${e.message}"), null)
}
}
}
override suspend fun updateBeneficiary(
beneficiaryId: Long?,
payload: BeneficiaryUpdatePayload?,
): DataState<String> {
return withContext(ioDispatcher) {
try {
val response = dataManager.beneficiaryApi.updateBeneficiary(beneficiaryId!!, payload)
DataState.Success(response.bodyAsText())
} catch (e: ClientRequestException) {
val errorMessage = extractErrorMessage(e.response)
DataState.Error(Exception(errorMessage), null)
} catch (e: IOException) {
DataState.Error(Exception("Network error: ${e.message ?: "Please check your connection"}"), null)
} catch (e: ServerResponseException) {
DataState.Error(Exception("Server error: ${e.message}"), null)
}
}
}
override suspend fun deleteBeneficiary(beneficiaryId: Long?): DataState<String> {
return withContext(ioDispatcher) {
try {
val response = dataManager.beneficiaryApi.deleteBeneficiary(beneficiaryId!!)
DataState.Success(response.bodyAsText())
} catch (e: ClientRequestException) {
val errorMessage = extractErrorMessage(e.response)
DataState.Error(Exception(errorMessage), null)
} catch (e: IOException) {
DataState.Error(Exception("Network error: ${e.message ?: "Please check your connection"}"), null)
} catch (e: ServerResponseException) {
DataState.Error(Exception("Server error: ${e.message}"), null)
}
}
}
override fun beneficiaryList(): Flow<DataState<List<Beneficiary>>> = flow {
try {
dataManager.beneficiaryApi.beneficiaryList()
.collect { response ->
emit(DataState.Success(response))
}
} catch (e: Exception) {
emit(DataState.Error(e, null))
}
}.flowOn(ioDispatcher)
}
```
---
## API Summary Table
| Endpoint | Method | Service Method | Repository Method | Priority |
|----------|--------|----------------|-------------------|----------|
| /self/beneficiaries/tpt | GET | beneficiaryList() | beneficiaryList() | P0 |
| /self/beneficiaries/tpt/template | GET | beneficiaryTemplate() | beneficiaryTemplate() | P0 |
| /self/beneficiaries/tpt | POST | createBeneficiary() | createBeneficiary() | P0 |
| /self/beneficiaries/tpt/{id} | PUT | updateBeneficiary() | updateBeneficiary() | P0 |
| /self/beneficiaries/tpt/{id} | DELETE | deleteBeneficiary() | deleteBeneficiary() | P0 |
---
## Account Type Mapping
| ID | Code | Value | Description |
|----|------|-------|-------------|
| 0 | accountType.share | Share Account | Share/Equity account |
| 1 | accountType.loan | Loan Account | Loan disbursement account |
| 2 | accountType.savings | Savings Account | Regular savings account |
---
## Error Responses
| Status Code | Error | Description | User Message |
|-------------|-------|-------------|--------------|
| 400 | Bad Request | Invalid request payload | "Please check your input" |
| 401 | Unauthorized | Invalid/expired token | "Please login again" |
| 403 | Forbidden | Insufficient permissions | "Access denied" |
| 404 | Not Found | Beneficiary doesn't exist | "Beneficiary not found" |
| 409 | Conflict | Duplicate beneficiary | "Beneficiary already exists" |
| 500 | Server Error | Internal server error | "Service unavailable" |
**Error Response Format**:
```json
{
"developerMessage": "Detailed error for debugging",
"httpStatusCode": "400",
"defaultUserMessage": "User-friendly error message",
"userMessageGlobalisationCode": "error.msg.code",
"errors": [
{
"developerMessage": "Field-specific error",
"defaultUserMessage": "Invalid account number format",
"userMessageGlobalisationCode": "validation.msg.accountNumber.invalid",
"parameterName": "accountNumber"
}
]
}
```
---
## Data Models Summary
### Beneficiary
```kotlin
@Serializable
@Parcelize
data class Beneficiary(
val id: Long? = null,
val name: String? = null,
val officeName: String? = null,
val clientName: String? = null,
val accountType: AccountType? = null,
val accountNumber: String? = null,
val transferLimit: Double? = null,
) : Parcelable
```
### BeneficiaryPayload (Create)
```kotlin
@Serializable
@Parcelize
data class BeneficiaryPayload(
val locale: String? = null,
val name: String? = null,
val accountNumber: String? = null,
val accountType: Int? = 0,
val transferLimit: Int? = 0,
val officeName: String? = null,
) : Parcelable
```
### BeneficiaryUpdatePayload (Update)
```kotlin
@Serializable
data class BeneficiaryUpdatePayload(
val name: String? = null,
val transferLimit: Int = 0,
)
```
### BeneficiaryTemplate
```kotlin
@Serializable
@Parcelize
data class BeneficiaryTemplate(
val accountTypeOptions: List<AccountTypeOption>? = null,
) : Parcelable
```
### AccountTypeOption
```kotlin
@Serializable
@Parcelize
data class AccountTypeOption(
val id: Int? = null,
val code: String? = null,
val value: String? = null,
) : Parcelable
```
### AccountType
```kotlin
@Serializable
@Parcelize
data class AccountType(
val id: Int? = null,
val code: String? = null,
val value: String? = null,
) : Parcelable
```
### BeneficiaryDetail (Helper)
```kotlin
class BeneficiaryDetail(
val accountNumber: String?,
val beneficiaryName: String?,
)
```
---
## Related Endpoints
These endpoints may be used in conjunction with beneficiary management:
| Endpoint | Method | Purpose |
|----------|--------|---------|
| /self/accounttransfers/template?type=tpt | GET | Get transfer template with beneficiary options |
| /self/accounttransfers?type=tpt | POST | Execute transfer to beneficiary |
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Initial production-level API documentation based on implementation |

View File

@ -1,647 +0,0 @@
# Beneficiary - Feature Specification
> **Purpose**: Manage third-party transfer beneficiaries for quick fund transfers
> **User Value**: Save and manage trusted recipients for faster, secure money transfers
> **Last Updated**: 2025-12-29
> **Status**: Production Design
---
## 1. Overview
### 1.1 Feature Summary
The Beneficiary feature enables users to manage a list of trusted recipients for third-party transfers (TPT). Users can view all saved beneficiaries, add new ones manually or via QR code, view beneficiary details, update beneficiary information, and delete beneficiaries. This feature streamlines the fund transfer process by eliminating the need to repeatedly enter recipient details.
### 1.2 User Stories
- As a user, I want to view all my saved beneficiaries in a list
- As a user, I want to filter beneficiaries by office or account type
- As a user, I want to add a new beneficiary manually with their account details
- As a user, I want to add a beneficiary by scanning a QR code
- As a user, I want to view detailed information about a beneficiary
- As a user, I want to update a beneficiary's name and transfer limit
- As a user, I want to delete a beneficiary I no longer need
- As a user, I want to confirm my actions before creating/updating beneficiaries
### 1.3 Design Principles
- **Security**: Authentication required before creating/updating beneficiaries
- **Simplicity**: Minimal steps to add or manage beneficiaries
- **Clarity**: Clear display of beneficiary information
- **Confirmation**: Multi-step process with review before submission
---
## 2. Screen Layout
### 2.1 Beneficiary List Screen
```
+-------------------------------------------------------------+
| <- Manage Beneficiaries |
+-------------------------------------------------------------+
| |
| [ Add + ] [ Filter ] |
| |
| +-------------------------------------------------------+ |
| | +---+ | |
| | | | John Doe | |
| | | JD| SA-0001234567 | |
| | | | Head Office | Savings Account | |
| | +---+ | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | +---+ | |
| | | | Jane Smith | |
| | | JS| LA-0009876543 | |
| | | | Branch Office | Loan Account | |
| | +---+ | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | +---+ | |
| | | | Mike Johnson | |
| | | MJ| SA-0005678901 | |
| | | | Head Office | Savings Account | |
| | +---+ | |
| +-------------------------------------------------------+ |
| |
| [Powered by Mifos] |
+-------------------------------------------------------------+
```
### 2.2 Beneficiary List - Filter Dialog
```
+-------------------------------------------------------------+
| <- Manage Beneficiaries |
+-------------------------------------------------------------+
| |
| [ Reset ] [ Apply ] [ X ] |
| |
| --------------------------------------------------------- |
| |
| Linked With 2 selected v |
| +-------------------------------------------------------+ |
| | [ ] Head Office | |
| | [x] Branch Office | |
| | [x] Regional Office | |
| +-------------------------------------------------------+ |
| |
| Type of Account 1 selected v |
| +-------------------------------------------------------+ |
| | [x] Savings Account | |
| | [ ] Loan Account | |
| | [ ] Share Account | |
| +-------------------------------------------------------+ |
| |
| [Powered by Mifos] |
+-------------------------------------------------------------+
```
### 2.3 Beneficiary List - Empty State
```
+-------------------------------------------------------------+
| <- Manage Beneficiaries |
+-------------------------------------------------------------+
| |
| |
| +--------+ |
| | ! | |
| +--------+ |
| |
| No beneficiaries found, please add |
| |
| +----------------------------------+ |
| | Add Beneficiary | |
| +----------------------------------+ |
| |
| [Powered by Mifos] |
+-------------------------------------------------------------+
```
### 2.4 Add/Update Beneficiary Screen
```
+-------------------------------------------------------------+
| <- Add Beneficiary |
+-------------------------------------------------------------+
| |
| +-------------------------------------------------------+ |
| | Beneficiary Name * | |
| | [ ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Account Number * | |
| | [ ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Select Account Type * v | |
| | [ ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Office Name * | |
| | [ ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Transfer Limit * | |
| | [ ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Submit Beneficiary | |
| +-------------------------------------------------------+ |
| |
| Skip the form? Upload or scan QR code |
| |
+-------------------------------------------------------------+
```
### 2.5 Beneficiary Confirmation Screen
```
+-------------------------------------------------------------+
| <- Add Beneficiary |
+-------------------------------------------------------------+
| |
| Validate Details |
| |
| +-------------------------------------------------------+ |
| | | |
| | Beneficiary Name John Doe | |
| | ----------------------------------------------------- | |
| | Office Head Office | |
| | ----------------------------------------------------- | |
| | Account Type Savings Account | |
| | ----------------------------------------------------- | |
| | Account Number SA-0001234567 | |
| | ----------------------------------------------------- | |
| | Transfer Limit 10000 | |
| | | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Confirm Details | |
| +-------------------------------------------------------+ |
| |
| [Powered by Mifos] |
+-------------------------------------------------------------+
```
### 2.6 Beneficiary Detail Screen
```
+-------------------------------------------------------------+
| <- Beneficiary Detail |
+-------------------------------------------------------------+
| |
| [ Delete ] [ Update ] |
| |
| +-------------------------------------------------------+ |
| | +-------+ | |
| | | | | |
| | | JD | | |
| | | | | |
| | +-------+ | |
| | John Doe | |
| | SA-0001234567 | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Beneficiary Name | |
| | [ John Doe ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Account Number | |
| | [ SA-0001234567 ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Select Account Type | |
| | [ Savings Account ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Office Name | |
| | [ Head Office ] | |
| +-------------------------------------------------------+ |
| |
| +-------------------------------------------------------+ |
| | Transfer Limit | |
| | [ 10000 ] | |
| +-------------------------------------------------------+ |
| |
+-------------------------------------------------------------+
```
### 2.7 Delete Confirmation Dialog
```
+-------------------------------------------------------------+
| |
| +-------------------------------------------------------+ |
| | | |
| | [Delete Icon] | |
| | | |
| | Delete Beneficiary | |
| | | |
| | Are you sure you want to delete this beneficiary? | |
| | | |
| | [ Cancel ] [ Delete ] | |
| | | |
| +-------------------------------------------------------+ |
| |
+-------------------------------------------------------------+
```
---
## 3. Sections Table
| Section | Component | Description | Priority |
|---------|-----------|-------------|----------|
| List Header | TopAppBar | Title "Manage Beneficiaries" with back navigation | P0 |
| Action Bar | Row | Add and Filter action buttons | P0 |
| Beneficiary Card | MifosBeneficiariesCard | Card with name, account, office, type | P0 |
| Filter Dialog | FilterSection | Office and Account Type filters with checkboxes | P1 |
| Empty State | EmptyDataView | Icon with message and Add button | P0 |
| Form Fields | MifosOutlinedTextField | Name, Account Number, Office, Transfer Limit | P0 |
| Account Type Dropdown | MifosDropDownTextField | Select account type (Savings/Loan/Share) | P0 |
| Submit Button | MifosButton | Submit Beneficiary action | P0 |
| QR Link | Text with ClickModifier | "Skip the form? Upload or scan QR code" | P1 |
| Details Card | MifosDetailsCard | Read-only beneficiary information | P0 |
| Confirm Button | MifosButton | Confirm Details action | P0 |
| Detail Top Card | MifosBeneficiaryTopCard | Avatar, name, account number | P0 |
| Delete Dialog | MifosAlertDialog | Delete confirmation with Cancel/Delete buttons | P0 |
| Powered Footer | MifosPoweredCard | "Powered by Mifos" branding | P2 |
---
## 4. User Interactions Table
| Interaction | Action | Effect | Navigation |
|-------------|--------|--------|------------|
| Tap Back Arrow | OnNavigate | Navigate to previous screen | popBackStack() |
| Tap Beneficiary Card | OnBeneficiaryItemClick | View beneficiary details | BeneficiaryDetailScreen |
| Tap Add Button | OnAddBeneficiaryClicked | Navigate to add form | BeneficiaryApplicationScreen |
| Tap Filter Button | ToggleFilter | Show filter dialog | FilterDialog |
| Apply Filter | GetFilterResults | Filter list by selected criteria | Dismiss dialog, update list |
| Reset Filter | ResetFilters | Clear all filters | Reset to full list |
| Submit Form | SubmitBeneficiary | Validate and navigate to confirmation | ConfirmationScreen |
| Confirm Details | SubmitBeneficiary | Navigate to authentication | AuthenticateScreen |
| Tap Update | OnUpdateBeneficiary | Navigate to edit form | BeneficiaryApplicationScreen (UPDATE) |
| Tap Delete | ShowDeleteConfirmation | Show delete dialog | Delete confirmation dialog |
| Confirm Delete | DeleteBeneficiary | Delete and navigate back | BeneficiaryListScreen |
| Tap QR Link | NavigateToQR | Navigate to QR scanner | QR Screen |
| Pull to Refresh | RefreshBeneficiaries | Reload beneficiary list | Refresh current screen |
---
## 5. State Model
### 5.1 BeneficiaryListState
```kotlin
data class BeneficiaryListState(
val networkStatus: Boolean = false,
val isRefreshing: Boolean = false,
val beneficiaries: List<Beneficiary> = emptyList(),
val template: BeneficiaryTemplate? = null,
val selectedAccounts: Set<String> = emptySet(),
val selectedOffices: Set<String> = emptySet(),
val offices: List<String?> = emptyList(),
val isEmpty: Boolean = false,
val isFilteredEmpty: Boolean = false,
val filteredBeneficiaries: List<Beneficiary> = emptyList(),
val dialogState: DialogState? = null,
val uiState: ScreenUiState = ScreenUiState.Loading,
) {
sealed interface DialogState {
data object Filters : DialogState
}
val isAnyFilterSelected = selectedAccounts.isNotEmpty() || selectedOffices.isNotEmpty()
}
sealed interface BeneficiaryListAction {
data object RefreshBeneficiaries : BeneficiaryListAction
data object OnAddBeneficiaryClicked : BeneficiaryListAction
data class OnBeneficiaryItemClick(val position: Long) : BeneficiaryListAction
data object OnNavigate : BeneficiaryListAction
data object ToggleFilter : BeneficiaryListAction
data object ResetFilters : BeneficiaryListAction
data object GetFilterResults : BeneficiaryListAction
data object DismissDialog : BeneficiaryListAction
data class OnAccountChange(val account: String) : BeneficiaryListAction
data class OnOfficeChange(val office: String) : BeneficiaryListAction
data object LoadBeneficiaries : BeneficiaryListAction
data class ReceiveNetworkStatus(val isOnline: Boolean) : BeneficiaryListAction
sealed interface Internal : BeneficiaryListAction {
data class ReceiveBeneficiaryResult(
val beneficiaryList: DataState<List<Beneficiary>>,
) : Internal
}
}
sealed interface BeneficiaryListEvent {
data object AddBeneficiaryClicked : BeneficiaryListEvent
data class BeneficiaryItemClick(val position: Long) : BeneficiaryListEvent
data object Navigate : BeneficiaryListEvent
}
```
### 5.2 BeneficiaryApplicationState
```kotlin
data class BeneficiaryApplicationState(
val topBarTitle: StringResource = Res.string.add_beneficiary,
val beneficiaryId: Long = -1L,
val networkUnavailable: Boolean = false,
val template: BeneficiaryTemplate? = null,
val beneficiary: Beneficiary? = null,
val beneficiaryState: BeneficiaryState = BeneficiaryState.CREATE_MANUAL,
val dialogState: DialogState? = null,
val accountTypeError: StringResource? = null,
val accountNumberError: StringResource? = null,
val officeNameError: StringResource? = null,
val transferLimitError: StringResource? = null,
val beneficiaryNameError: StringResource? = null,
val accountType: Int = -1,
val accountNumber: String = "",
val officeName: String = "",
val transferLimit: String = "",
val beneficiaryName: String = "",
val networkStatus: Boolean = false,
val uiState: ScreenUiState = ScreenUiState.Loading,
val shoeOverlay: Boolean = false,
) {
sealed interface DialogState {
data class Error(val message: String) : DialogState
}
val isEnabled = accountType != -1 &&
accountNumber.isNotEmpty() &&
officeName.isNotEmpty() &&
transferLimit.isNotEmpty() &&
beneficiaryName.isNotEmpty()
}
sealed interface BeneficiaryApplicationAction {
data object LoadBeneficiaryTemplate : BeneficiaryApplicationAction
data object SubmitBeneficiary : BeneficiaryApplicationAction
data object OnNavigate : BeneficiaryApplicationAction
data object OnRetry : BeneficiaryApplicationAction
data object NavigateToQR : BeneficiaryApplicationAction
data class OnAccountTypeChanged(val accountType: Int) : BeneficiaryApplicationAction
data class OnAccountNumberChanged(val accountNumber: String) : BeneficiaryApplicationAction
data class OnOfficeNameChanged(val officeName: String) : BeneficiaryApplicationAction
data class OnTransferLimitChanged(val transferLimit: String) : BeneficiaryApplicationAction
data class OnBeneficiaryNameChanged(val beneficiaryName: String) : BeneficiaryApplicationAction
data class ReceiveNetworkStatus(val isOnline: Boolean) : BeneficiaryApplicationAction
sealed interface Internal : BeneficiaryApplicationAction {
data class ReceiveBeneficiaryResult(
val beneficiaryList: DataState<List<Beneficiary>>,
val beneficiaryTemplate: DataState<BeneficiaryTemplate>,
) : Internal
}
}
sealed interface BeneficiaryApplicationEvent {
data object Navigate : BeneficiaryApplicationEvent
data class SubmitBeneficiary(
val beneficiaryId: Long,
val beneficiaryState: String,
val name: String,
val officeName: String,
val accountType: Int,
val accountNumber: String,
val transferLimit: Int,
) : BeneficiaryApplicationEvent
data object NavigateToQR : BeneficiaryApplicationEvent
}
```
### 5.3 BeneficiaryApplicationConfirmationState
```kotlin
data class BeneficiaryApplicationConfirmationState(
val details: Map<StringResource, String> = emptyMap(),
val topBarTitle: StringResource = Res.string.add_beneficiary,
val beneficiaryId: Long,
val name: String,
val officeName: String,
val accountType: Int,
val accountNumber: String,
val transferLimit: Int,
val networkUnavailable: Boolean = false,
val beneficiaryState: BeneficiaryState = BeneficiaryState.CREATE_MANUAL,
val dialogState: DialogState? = null,
val uiState: ScreenUiState? = ScreenUiState.Success,
val showOverlay: Boolean = false,
val networkStatus: Boolean = false,
) {
sealed interface DialogState {
data object Network : DialogState
}
}
sealed interface BeneficiaryApplicationConfirmationAction {
data object SubmitBeneficiary : BeneficiaryApplicationConfirmationAction
data class ReceiveNetworkStatus(val isOnline: Boolean) : BeneficiaryApplicationConfirmationAction
data object OnNavigate : BeneficiaryApplicationConfirmationAction
sealed interface Internal : BeneficiaryApplicationConfirmationAction {
data class ReceiveAuthenticationResult(val result: Boolean) : Internal
data class ReceiveSubmitBeneficiary(val result: DataState<String>) : Internal
data class ReceiveUpdateBeneficiary(val result: DataState<String>) : Internal
}
}
sealed interface BeneficiaryApplicationConfirmationEvent {
data object Navigate : BeneficiaryApplicationConfirmationEvent
data class NavigateToStatus(
val eventType: String,
val eventDestination: String,
val title: String,
val subtitle: String,
val buttonText: String,
) : BeneficiaryApplicationConfirmationEvent
data class NavigateToAuthenticate(
val status: String = EventType.SUCCESS.name,
) : BeneficiaryApplicationConfirmationEvent
}
```
### 5.4 BeneficiaryDetailState
```kotlin
data class BeneficiaryDetailState(
val beneficiaryId: Long = -1L,
val beneficiary: Beneficiary? = null,
val beneficiaryDialog: DialogState? = null,
val networkStatus: Boolean = false,
val uiState: ScreenUiState = ScreenUiState.Loading,
val showOverlay: Boolean = false,
) {
sealed interface DialogState {
data class Error(val message: String) : DialogState
data class Confirmation(val message: String) : DialogState
}
}
sealed interface BeneficiaryDetailAction {
data object OnRefresh : BeneficiaryDetailAction
data object OnUpdateBeneficiary : BeneficiaryDetailAction
data object DeleteBeneficiary : BeneficiaryDetailAction
data object OnNavigate : BeneficiaryDetailAction
data object ErrorDialogDismiss : BeneficiaryDetailAction
data object ShowDeleteConfirmation : BeneficiaryDetailAction
data class ReceiveNetworkStatus(val isOnline: Boolean) : BeneficiaryDetailAction
sealed interface Internal : BeneficiaryDetailAction {
data class ReceiveBeneficiaryResult(val result: DataState<List<Beneficiary>>) : Internal
data class ReceiveDeleteBeneficiary(val result: DataState<String>) : Internal
}
}
sealed interface BeneficiaryDetailEvent {
data object NavigateBack : BeneficiaryDetailEvent
data class UpdateBeneficiary(val beneficiaryId: Long) : BeneficiaryDetailEvent
}
```
### 5.5 BeneficiaryState Enum
```kotlin
enum class BeneficiaryState {
CREATE_MANUAL,
CREATE_QR,
UPDATE,
}
```
---
## 6. API Requirements
| Endpoint | Method | Purpose | Priority |
|----------|--------|---------|----------|
| /self/beneficiaries/tpt | GET | Fetch list of all beneficiaries | P0 |
| /self/beneficiaries/tpt/template | GET | Fetch account type options | P0 |
| /self/beneficiaries/tpt | POST | Create new beneficiary | P0 |
| /self/beneficiaries/tpt/{id} | PUT | Update beneficiary name/limit | P0 |
| /self/beneficiaries/tpt/{id} | DELETE | Delete a beneficiary | P0 |
---
## 7. Edge Cases & Error Handling
| Scenario | UI Behavior | Recovery |
|----------|-------------|----------|
| No internet | Show network error with retry | Auto-retry on reconnect |
| API timeout | Show error state | Pull-to-refresh or Retry button |
| Empty list | Show empty state with Add CTA | Tap "Add Beneficiary" |
| No filter results | Show "No filtered beneficiary found" | Reset filters |
| Invalid form input | Show field-level error messages | Fix errors and resubmit |
| Create failed | Navigate to status screen with failure | "Try Again" button |
| Update failed | Navigate to status screen with failure | "Try Again" button |
| Delete failed | Show error dialog | Dismiss and retry |
| Authentication failed | Stay on confirmation screen | Re-authenticate |
| Duplicate beneficiary | API error shown | Edit details |
---
## 8. Form Validation Rules
| Field | Validation | Error Message |
|-------|------------|---------------|
| Beneficiary Name | Required, non-empty | "Enter beneficiary name" |
| Account Number | Required (except UPDATE), non-empty | "Enter account number" |
| Account Type | Required (except UPDATE), must be selected | "Select account type" |
| Office Name | Required (except UPDATE), non-empty | "Enter office name" |
| Transfer Limit | Required, must be valid number | "Enter transfer limit" / "Invalid amount" |
---
## 9. Navigation Flow
```
BeneficiaryNavRoute (Root)
|
+-- BeneficiaryListScreen (Start Destination)
| |
| +-- [Add] --> BeneficiaryApplicationScreen (CREATE_MANUAL)
| | |
| | +-- [Submit] --> BeneficiaryConfirmationScreen
| | | |
| | | +-- [Confirm] --> AuthenticateScreen
| | | | |
| | | | +-- [Success] --> StatusScreen
| | | | |
| | | | +-- [Failure] --> StatusScreen
| | |
| | +-- [QR Link] --> QRScreen
| |
| +-- [Card Tap] --> BeneficiaryDetailScreen
| |
| +-- [Update] --> BeneficiaryApplicationScreen (UPDATE)
| | |
| | +-- (same as above)
| |
| +-- [Delete] --> Confirmation Dialog
| |
| +-- [Confirm] --> Delete API --> NavigateBack
```
---
## 10. Performance Requirements
| Metric | Target | Implementation |
|--------|--------|----------------|
| List load | < 1s | Lazy loading with LazyColumn |
| Filter apply | < 100ms | In-memory filtering |
| Form validation | Instant | Local validation |
| API calls | < 2s | Network timeout handling |
| Screen transition | < 300ms | Compose navigation |
---
## 11. Accessibility
| Feature | Implementation |
|---------|----------------|
| Screen Reader | contentDescription on all interactive elements |
| Font Scaling | Supports up to 200% scaling |
| Touch Targets | 48dp minimum tap target |
| Color Contrast | WCAG AA compliant (4.5:1) |
| Focus Navigation | Logical tab order through form fields |
---
## 12. Security Considerations
| Feature | Implementation |
|---------|----------------|
| Authentication | Required before create/update submission |
| Transfer Limit | Enforced per beneficiary |
| Account Validation | Server-side account number validation |
| Session Management | Uses existing auth session |
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Initial production-level specification based on implementation |

View File

@ -1,68 +0,0 @@
# Beneficiary Feature - Implementation Status
> **Last Updated**: 2025-12-29
> **Overall Status**: ✅ Done
---
## Implementation Checklist
- [x] SPEC.md created
- [x] API.md created
- [x] Network: Services exist (BeneficiaryService)
- [x] Data: Repository exists (BeneficiaryRepository)
- [x] Feature: ViewModels + Screens
- [x] Navigation: Routes registered
- [x] DI: Modules registered
- [x] STATUS.md updated
---
## Layer Status
| Layer | Status | Files |
|-------|--------|-------|
| Network | ✅ | BeneficiaryService.kt |
| Data | ✅ | BeneficiaryRepository.kt, BeneficiaryRepositoryImp.kt |
| Feature | ✅ | BeneficiaryListViewModel.kt, BeneficiaryListScreen.kt, BeneficiaryApplicationViewModel.kt, BeneficiaryApplicationScreen.kt, BeneficiaryDetailViewModel.kt, BeneficiaryDetailScreen.kt, BeneficiaryApplicationConfirmationViewModel.kt, BeneficiaryApplicationConfirmationScreen.kt |
| DI | ✅ | BeneficiaryModule.kt |
| Navigation | ✅ | BeneficiaryListNavigation.kt, BeneficiaryApplicationNavRoute.kt, BeneficiaryApplicationConfirmationNavigation.kt, BeneficiaryNavRoute.kt |
---
## Files
### Network Layer
- `core/network/services/BeneficiaryService.kt`
### Data Layer
- `core/data/repository/BeneficiaryRepository.kt`
- `core/data/repositoryImpl/BeneficiaryRepositoryImp.kt`
### Feature Layer
- `feature/beneficiary/beneficiaryList/BeneficiaryListViewModel.kt`
- `feature/beneficiary/beneficiaryList/BeneficiaryListScreen.kt`
- `feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationViewModel.kt`
- `feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationScreen.kt`
- `feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationContent.kt`
- `feature/beneficiary/beneficiaryDetail/BeneficiaryDetailViewModel.kt`
- `feature/beneficiary/beneficiaryDetail/BeneficiaryDetailScreen.kt`
- `feature/beneficiary/beneficiaryDetail/BeneficiaryDetailContent.kt`
- `feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationViewModel.kt`
- `feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationScreen.kt`
- `feature/beneficiary/navigation/BeneficiaryNavRoute.kt`
- `feature/beneficiary/di/BeneficiaryModule.kt`
---
## Gaps
None identified.
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Initial status documentation |

View File

@ -1,349 +0,0 @@
# Beneficiary - Figma First Draft Prompts
> **Tool**: Figma First Draft (Shift+I in Figma)
> **Style**: Trusted Contacts Fintech, Material Design 3
> **Format**: Natural language prompts optimized for Figma AI
---
## How to Use
1. Open Figma -> Create new design file
2. Press `Shift + I` or click "Actions" -> "First Draft"
3. Copy each prompt below
4. Generate -> Iterate -> Refine
---
## Screen 1: Trusted Contacts Hub
```
Design a modern mobile trusted contacts hub for a fintech banking app inspired by Venmo and Zelle.
At the top, show a back arrow with "Trusted Contacts" title and add contact/scan QR icons on the right.
Add a search bar with a microphone icon for voice search.
Create a stunning Favorites section with a purple gradient background. Show a star icon with "FAVORITES" header. Display horizontally scrolling circular avatars (64px) with user initials inside, names below, and total amount transferred to each. Include an "Add" button at the end.
Add a Suggested section with "Suggested" header and "See All >" link. Show a suggestion card with avatar, name, context text like "Sent 3x this month - Monthly rent", and a gradient "Send $50" quick action button.
Create filter chips in a row: All (selected with gradient), Family, Business, Account type dropdown.
Show an alphabetically organized contacts list. Each contact card should have an avatar with a verification ring (green for verified, amber for pending), name in medium weight, masked account number, account type, a relationship tag chip (like "Family" or "Business"), a trust indicator badge, last transfer info, and a "Send" button on the right.
Add a floating action button with gradient background and "+ Add" text in the bottom right corner.
Style it like Venmo's contact list with trust indicators - clean and relationship-focused with purple accent colors.
```
---
## Screen 2: Contact Detail
```
Design a contact detail screen showing comprehensive information about a trusted payment contact.
Show a back arrow with "Contact" title and star (favorite), edit, and menu icons on the right.
Create a hero card with purple gradient background. Display a large circular avatar (80px) with a glowing green verification ring around it and initials inside. Show the contact name "John Doe" in large white text, masked account number with account type, and a trust badge showing "Trusted Contact" with checkmark. Add stats showing "24 transfers • Since Mar 2024".
Add a Quick Actions row with three buttons: "Send Money" as a gradient filled button, "Schedule Payment" as outlined, and "Request Money" as outlined.
Create a Transfer Summary card showing relationship analytics. Display two stat boxes side by side: "Total Sent $12,450" and "Total Received $3,200". Add a horizontal progress bar showing 80% sent in gradient color and 20% received in gray. Show additional stats: "Average Transfer: $518" and "Most Common: Monthly payment".
Add a Recent Activity section with "See All >" link. Show transaction items with directional arrows (up-right for sent in red, down-left for received in green), amount, time ago, and description. Use dividers between items.
Create an Account Information section with key-value pairs in a clean grid: Account Number with copy icon, Account Type, Office, Transfer Limit, Relationship tag, and Added On date.
Add a security footer with lock icon showing "256-bit encryption • Verified contact".
Make it feel like a trusted relationship hub with clear visual hierarchy.
```
---
## Screen 3: Quick Transfer from Contact
```
Design a quick transfer screen for sending money to a specific trusted contact.
Show a back arrow with "Send to John" as the title.
Create a recipient card at the top showing the contact's avatar with verified badge, name, masked account number, and "Trusted Contact" indicator.
Add a large centered amount input showing "$0.00" that updates as the user types. Use a gradient underline below the amount. Show "Available: $5,420.00 in Savings" as helper text below.
Create a Quick Amounts section with the label "Quick Amounts (based on history)". Show four amount chips: $250 labeled "Common", $500 labeled "Usual" with a star indicator (AI suggestion), $750, and $1,000.
Add a Note section with "Add a note (optional)" label, an input field with placeholder "What's this for?", and chips for recent notes used with this contact like "Monthly rent" and "Utilities split".
Display a custom number keypad in a 3x4 grid: numbers 1-9, decimal point, 0, and backspace.
Add a full-width gradient button at the bottom: "Review Transfer ->".
Style it for fast, frictionless payments with smart suggestions based on transfer history.
```
---
## Screen 4: Add New Contact - Smart Flow
```
Design an add new contact screen offering multiple methods to add trusted contacts.
Show a back arrow with "Add Trusted Contact" title.
Create a hero section with purple gradient background showing a group/people icon and "Add a Trusted Contact" header with "Choose how you'd like to add a new contact" subtitle.
Display four method cards stacked vertically:
1. First card (recommended) - Use gradient background with camera icon, "Scan QR Code" title, "Instantly add by scanning their QR" description, and a "Fast" badge with star.
2. Second card - Phone icon with "From Phone Contacts" title and "Import from your existing contacts" description.
3. Third card - Pencil icon with "Enter Manually" title and "Type account details directly" description.
4. Fourth card - Link icon with "Share Link" title and "Get your link to share with contacts" description.
Add a tip card with a lightbulb icon explaining "QR scanning is the fastest and most secure way to add contacts with zero typing errors".
Include a security footer with lock icon: "All contacts are verified before first transfer".
Make the QR option stand out as the recommended path while keeping other options accessible.
```
---
## Screen 5: Manual Entry Flow - Step 1 Account
```
Design step 1 of a 4-step contact addition flow for entering account information.
Show a back arrow with "Add Contact" title.
Create a progress indicator with four connected steps: Account (active/filled), Office, Details, Review. Use a line connecting the steps with the current step highlighted in gradient color.
Add a section header with gradient background showing a bank icon and "Account Information" title.
Create an Account Number input field with label "Account Number *", a text field prefixed with "SA-", a paste/copy icon, and helper text "Enter the complete account number".
Add an Account Type selector with label "Account Type *" and three radio card options stacked vertically: "Savings Account" (selected with gradient border, marked "Most common for transfers"), "Loan Account" ("For loan repayments"), and "Share Account" ("For share purchases").
Include a full-width gradient "Continue ->" button at the bottom.
Style it as a clean form wizard with clear progress indication.
```
---
## Screen 6: Manual Entry Flow - Step 2 Office
```
Design step 2 of the contact addition flow for selecting office/branch.
Show a back arrow with "Add Contact" title.
Create a progress indicator showing Account (checkmarked complete), Office (active/filled), Details, Review.
Add a section header with gradient background showing a building icon and "Office / Branch" title.
Include a search input with placeholder "Search offices...".
Create a Popular Offices section with radio cards for: "Head Office" (selected with gradient, has "Popular" badge, "Main branch, downtown"), "Branch Office" ("Secondary branch, midtown"), and "Regional Center" ("Regional hub, north district").
Add a Transfer Limit input section with label "Transfer Limit *", a large editable amount "$10,000", and quick set chips: $5,000, $10,000 (starred as most common), $25,000, $50,000.
Include two navigation buttons at the bottom: "← Back" as outlined and "Continue →" as gradient filled.
```
---
## Screen 7: Manual Entry Flow - Step 3 Details
```
Design step 3 of the contact addition flow for entering contact details.
Show a back arrow with "Add Contact" title.
Create a progress indicator showing Account and Office (checkmarked), Details (active/filled), Review.
Add a section header with gradient background showing a person icon and "Contact Details" title.
Create a Contact Name input with label "Contact Name *", text field showing "John Doe", and helper text "How you'll recognize this contact".
Add a Relationship Tags section with label "Relationship Tag (optional)" and a 2x4 chip grid: Family (with emoji), Friend, Business, Landlord, Vendor, School, Medical, and Custom (+).
Include a checkbox option "Add to Favorites" with helper text "Quick access from home screen".
Create a live Preview section showing how the contact card will appear with the entered information.
Include navigation buttons: "← Back" and "Review & Save →" gradient button.
```
---
## Screen 8: Manual Entry Flow - Step 4 Review
```
Design the final review step of the contact addition flow.
Show a back arrow with "Add Contact" title.
Create a progress indicator showing all previous steps checkmarked and Review as active.
Add a section header with gradient background showing a checkmark icon and "Review & Confirm" title.
Display a centered avatar section with large initials "JD", name "John Doe" below, and relationship tag "Business Partner".
Create a details card with key-value rows, each with an edit pencil icon on the right: Account Number (SA-0001234567), Account Type (Savings Account with icon), Office (Head Office with icon), Transfer Limit ($10,000.00), and Relationship (Business Partner with icon).
Add two security badges: lock icon with "Contact will be verified before first transfer" and shield icon with "Protected by 256-bit encryption".
Include navigation buttons: "← Back" and "Add Trusted Contact" as the primary gradient action.
Make it feel like a final confirmation with easy inline editing.
```
---
## Screen 9: Contact Added Success
```
Design a success screen celebrating a newly added contact.
Center a large success animation with a green circular checkmark that has a drawing animation. Add confetti particles floating around.
Show "Contact Added!" as the main headline in large bold text.
Display the newly added contact in a preview card: avatar with initials, name, masked account number, and relationship tag.
Add a verification notice with hourglass icon: "Verification pending" with "First transfer will verify" explanation.
Include two action buttons: "Send Money Now ->" as the primary gradient button (most likely next action) and "Back to Contacts" as a secondary outlined button.
Make it feel celebratory and guide the user toward their next action.
```
---
## Screen 10: Edit Contact
```
Design an edit contact screen allowing modification of editable fields.
Show a back arrow with "Edit Contact" title and "Save" text button on the right.
Create a hero section with gradient background showing the contact's avatar and masked account number (non-editable).
Add an info banner with info icon explaining "Only name, relationship, and limit can be changed".
Create editable fields: Contact Name with edit pencil icon, Account Number locked with lock icon and explanation "Cannot be changed for security", Relationship Tags as a chip selector with current selection highlighted, and Transfer Limit as an editable amount with note "Increased from $10,000".
Include two buttons: "Save Changes" as gradient primary and "Remove Contact" as a red/danger outlined button.
Clearly distinguish between editable and locked fields for security.
```
---
## Screen 11: Delete Confirmation Modal
```
Design a confirmation modal for removing a trusted contact.
Create a dimmed background overlay.
Show a centered modal card with 24dp rounded corners.
Display a large amber warning triangle icon at the top.
Add the title "Remove Trusted Contact?" in bold.
Show a preview of the contact being deleted: avatar, name, masked account number, with stats "24 transfers • $15,650 total" to emphasize the relationship history.
Include warning text: "This will remove John from your trusted contacts. You'll need to add them again to send money." Add a warning icon with "This cannot be undone".
Display two action buttons: "Cancel" as outlined (safe option) and "Remove" as red filled (destructive action).
Make the consequences clear while keeping the safe option prominent.
```
---
## Screen 12: Empty State
```
Design an empty state for when the user has no trusted contacts.
Keep the header with "Trusted Contacts" title and add/scan icons.
Show the search bar as visible but inactive.
Center a friendly illustration of people/contacts with a subtle floating animation.
Display "No Trusted Contacts Yet" as the headline with "Add your first contact to start sending money securely" as the description.
Create a benefits list with checkmarks: Quick one-tap transfers, Secure verified contacts, Track payment history, Organized with tags.
Add a prominent gradient button: "Add Your First Contact".
Make it feel welcoming and motivating, not empty or broken.
```
---
## Component Prompts
### Trust Badge Component
```
Design a trust verification badge component.
Create two variants:
1. Verified: Green background pill with white checkmark icon and "Trusted Contact" text
2. Pending: Amber background pill with hourglass icon and "Pending Verification" text
Height should be 24dp with rounded pill shape.
```
### Contact Card Component
```
Design a contact card for the contacts list.
Create a full-width card about 88dp tall with 16dp padding.
On the left, show a 48dp circular avatar with a colored ring around it (green for verified, amber for pending) and initials inside.
Show the contact name in medium weight, masked account number and type in smaller gray text below.
Add a relationship tag chip (like "Family" with emoji).
Show a trust indicator badge.
Display last transfer info in small text.
Include a "Send" button on the right side.
Add swipe actions for Edit and Delete.
```
---
## Tips for Figma First Draft
1. **Iterate**: Generate once, then refine with follow-up prompts
2. **Colors**: Use "#667EEA to #764BA2" for primary gradient
3. **Reference**: Say "like Venmo" or "Zelle trusted contacts" for context
4. **Trust Indicators**: Emphasize verified vs pending states
5. **Relationships**: Include tags and transfer history
6. **Responsive**: Mention "393px width for mobile" for correct sizing
---
## After Generation
1. Review generated designs for consistency
2. Create a color style library
3. Build component variants for trust states
4. Link screens with prototype connections
5. Export and update `FIGMA_LINKS.md`

View File

@ -1,495 +0,0 @@
# Beneficiary - Google Stitch Prompts
> **Tool**: [Google Stitch](https://stitch.withgoogle.com)
> **Style**: Material Design 3, Trusted Contacts Fintech
> **Format**: Copy each prompt block directly into Stitch
---
## Design System Reference
```
Primary Gradient: #667EEA -> #764BA2
Secondary Gradient: #11998E -> #38EF7D
Success/Verified: #00D09C
Warning/Pending: #FFB800
Error/Danger: #FF4757
Text Primary: #1F2937
Text Secondary: #6B7280
Surface: #FFFFFF
Screen Size: 393 x 852 pixels (Android)
```
---
## Screen 1: Trusted Contacts Hub
```
Mobile trusted contacts hub, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Trusted Contacts" title
- Add contact, scan QR icons right
Search Bar:
- Search input with mic icon
Favorites Section:
- Primary gradient background card
- Star icon "FAVORITES" header
- Horizontal scroll avatars 64dp
- Each: initials, name, total transferred
- Add button at end
Suggested Section:
- "Suggested" header with "See All >"
- Card: avatar, name, context, gradient "Send $50" button
- Based on AI/history
Filter Chips:
- All (selected), Family, Business, Account type
Contacts List:
- Alphabetical sections: "A", "J" etc.
- Contact cards:
- Avatar with verified badge (green ring) or pending (amber)
- Name, account masked, account type
- Relationship tag chip
- Trust indicator: checkmark "Trusted" or hourglass "Pending"
- Last transfer info
- Send button on right
FAB:
- Gradient "+ Add" floating button bottom right
Bottom Navigation:
- Home, Accounts, FAB Transfer, Profile
```
---
## Screen 2: Contact Detail
```
Mobile contact detail, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Contact" title
- Star (favorite), edit, menu icons
Hero Card:
- Primary gradient full width
- Large avatar with verified badge (green glow ring)
- Initials "JD" inside avatar
- Name "John Doe" 24sp white
- Account masked "****4567 • Savings"
- Trust badge: checkmark "Trusted Contact"
- Stats: "24 transfers • Since Mar 2024"
Quick Actions Row:
- Three buttons: "Send Money" (gradient filled), "Schedule Payment", "Request Money"
Transfer Summary Card:
- "Transfer Summary" header
- Two stat boxes: "Total Sent $12,450" | "Total Received $3,200"
- Horizontal bar: 80% sent (gradient), 20% received (gray)
- Stats: "Average Transfer: $518", "Most Common: Monthly payment"
Recent Activity Section:
- "Recent Activity" header with "See All >"
- Transaction items:
- Arrow up-right (sent) or down-left (received)
- "Sent $500", "3 days ago", "Monthly rent payment"
- Dividers between items
Account Information Card:
- "Account Information" header
- Key-value pairs: Account Number (with copy icon), Account Type, Office, Transfer Limit, Relationship tag, Added On
Security Footer:
- Lock icon "256-bit encryption • Verified contact"
```
---
## Screen 3: Quick Transfer from Contact
```
Mobile quick transfer, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Send to John" title
Recipient Card:
- Avatar with verified badge
- Name, account masked, "Trusted Contact" badge
Amount Input:
- Large centered "$0.00" editable
- Underline primary gradient
- "Available: $5,420.00 in Savings" helper
Quick Amounts Section:
- "Quick Amounts (based on history)" label
- Four chips: $250 "Common", $500 "Usual" (starred), $750, $1,000
Note Section:
- "Add a note (optional)" label
- Input field "What's this for?"
- Recent notes chips: "Monthly rent", "Utilities split"
Number Keypad:
- 3x4 grid: 1-9, ., 0, backspace
Continue Button:
- Full width gradient "Review Transfer ->"
```
---
## Screen 4: Add New Contact - Smart Flow
```
Mobile add contact methods, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Add Trusted Contact" title
Hero Section:
- Primary gradient
- Group icon "Add a Trusted Contact"
- "Choose how you'd like to add a new contact"
Method Cards:
- Card 1 (gradient, recommended):
- Camera icon "Scan QR Code"
- "Instantly add by scanning their QR"
- Star badge "Fast"
- Card 2:
- Phone icon "From Phone Contacts"
- "Import from your existing contacts"
- Card 3:
- Pencil icon "Enter Manually"
- "Type account details directly"
- Card 4:
- Link icon "Share Link"
- "Get your link to share with contacts"
Tip Card:
- Lightbulb icon
- "QR scanning is the fastest and most secure way to add contacts with zero typing errors"
Security Footer:
- Lock icon "All contacts are verified before first transfer"
```
---
## Screen 5: Manual Entry Step 1 - Account
```
Mobile add contact step 1, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Add Contact" title
Progress Indicator:
- Four steps: Account (filled), Office, Details, Review
- Connected line between steps
Section Header:
- Primary gradient "Account Information" with bank icon
Account Number Input:
- Label "Account Number *"
- Text field with "SA-" prefix, paste icon
- Helper text "Enter the complete account number"
Account Type Selector:
- Label "Account Type *"
- Three radio cards:
- Savings Account (gradient selected, "Most common")
- Loan Account
- Share Account
Continue Button:
- Full width gradient "Continue ->"
```
---
## Screen 6: Manual Entry Step 2 - Office
```
Mobile add contact step 2, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Add Contact" title
Progress Indicator:
- Account (checkmark), Office (filled), Details, Review
Section Header:
- Primary gradient "Office / Branch" with building icon
Search Input:
- Search icon "Search offices..."
Popular Offices:
- "Popular Offices" label
- Radio cards:
- Head Office (gradient selected, "Popular" badge)
- Branch Office
- Regional Center
- Each with icon, name, description
Transfer Limit Input:
- Label "Transfer Limit *"
- Large "$10,000" editable
- Quick set chips: $5,000, $10,000 (starred), $25,000, $50,000
Navigation Buttons:
- "Back" outline, "Continue ->" gradient
```
---
## Screen 7: Manual Entry Step 3 - Details
```
Mobile add contact step 3, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Add Contact" title
Progress Indicator:
- Account (check), Office (check), Details (filled), Review
Section Header:
- Primary gradient "Contact Details" with person icon
Contact Name Input:
- Label "Contact Name *"
- Text field "John Doe"
- Helper "How you'll recognize this contact"
Relationship Tags:
- Label "Relationship Tag (optional)"
- Chip grid 2x4:
- Family, Friend, Business, Landlord
- Vendor, School, Medical, Custom +
Favorite Checkbox:
- Unchecked "Add to Favorites"
- Helper "Quick access from home screen"
Preview Card:
- "Preview:" label
- Contact card mockup with entered data
Navigation Buttons:
- "Back" outline, "Review & Save ->" gradient
```
---
## Screen 8: Manual Entry Step 4 - Review
```
Mobile add contact step 4, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Add Contact" title
Progress Indicator:
- All steps checkmarked, Review filled
Section Header:
- Primary gradient "Review & Confirm" with checkmark icon
Avatar Section:
- Large centered avatar "JD"
- Name "John Doe"
- Relationship tag "Business Partner"
Details Card:
- Key-value rows with edit pencil icons:
- Account Number: SA-0001234567
- Account Type: Savings Account
- Office: Head Office
- Transfer Limit: $10,000.00
- Relationship: Business Partner
Security Badges:
- Lock "Contact will be verified before first transfer"
- Shield "Protected by 256-bit encryption"
Navigation Buttons:
- "Back" outline, "Add Trusted Contact" gradient
```
---
## Screen 9: Contact Added Success
```
Mobile contact added success, Material Design 3, 393x852px
Success Animation:
- Animated checkmark in green circle
- Confetti particles
Success Message:
- "Contact Added!" 28sp bold
Contact Preview Card:
- Avatar "JD"
- Name "John Doe"
- Account masked, relationship tag
Verification Notice:
- Hourglass icon "Verification pending"
- "First transfer will verify"
Action Buttons:
- "Send Money Now ->" gradient primary
- "Back to Contacts" outline secondary
```
---
## Screen 10: Edit Contact
```
Mobile edit contact, Material Design 3, fintech, 393x852px
Top Bar:
- Back arrow, "Edit Contact" title, "Save" text button
Hero Section:
- Primary gradient
- Avatar "JD"
- Account number masked
Info Banner:
- Info icon "Only name, relationship, and limit can be changed"
Editable Fields:
- Contact Name: "John Doe" with edit pencil
- Account Number: locked with lock icon
- Relationship Tags: chip selector with Business selected
- Transfer Limit: "$15,000" editable
Buttons:
- "Save Changes" gradient primary
- "Remove Contact" red/danger outline
```
---
## Screen 11: Delete Confirmation Modal
```
Mobile delete confirmation modal, Material Design 3
Dimmed Background
Modal Card:
- 24dp corners, centered
Warning Icon:
- Amber warning triangle
Title:
- "Remove Trusted Contact?"
Contact Preview:
- Avatar, name, account masked
- Stats: "24 transfers • $15,650 total"
Warning Text:
- "This will remove John from your trusted contacts."
- "You'll need to add them again to send money."
- Warning icon "This cannot be undone"
Buttons:
- "Cancel" outline
- "Remove" red filled
```
---
## Screen 12: Empty State
```
Mobile beneficiaries empty state, Material Design 3, 393x852px
Top Bar:
- Back arrow, "Trusted Contacts" title
- Add, scan icons
Search Bar visible
Center Content:
- Floating people illustration
- "No Trusted Contacts Yet" 20sp bold
- "Add your first contact to start sending money securely"
Benefits List:
- Checkmarks: Quick one-tap transfers, Secure verified contacts, Track payment history, Organized with tags
CTA Button:
- Gradient "Add Your First Contact"
```
---
## Components
### ContactCard
```
Contact card component, Material Design 3:
- Height: 88dp, padding: 16dp
- Avatar: 48dp with status ring (green verified, amber pending)
- Name: 16sp Medium, account: 14sp Regular
- Relationship chip, trust badge
- Send button on right
- Swipe actions: Edit, Delete
```
### TrustBadge
```
Trust badge component, Material Design 3:
- Verified: green checkmark, "Trusted Contact"
- Pending: amber hourglass, "Pending Verification"
- Height: 24dp pill shape
```
### QuickAmountChip
```
Quick amount chip, Material Design 3:
- Height: 48dp
- Amount: 16sp Medium
- Helper label: 12sp Secondary
- Selected: gradient fill, white text
- Starred: sparkle indicator
```
### RelationshipTag
```
Relationship tag chip, Material Design 3:
- Height: 32dp
- Emoji prefix: Family, Friend, Business, etc.
- Selected: primary border, tinted background
- Unselected: gray outline
```
---
## Quick Start
1. Open [stitch.withgoogle.com](https://stitch.withgoogle.com)
2. Create project "Mifos Mobile - Beneficiary"
3. Copy each screen prompt -> Generate
4. Generate components separately for reuse
5. Export all to Figma when done

View File

@ -1,579 +0,0 @@
# Client Charges - API Reference
> **Last Updated**: 2025-12-29
---
## Base URL
```
https://tt.mifos.community/fineract-provider/api/v1/self/
```
---
## Endpoints Required
### 1. Get Client Charges
**Endpoint**: `GET /clients/{clientId}/charges`
**Purpose**: Fetches all charges associated with the client (paginated response)
**Request**:
```
Headers:
Authorization: Basic {token}
Fineract-Platform-TenantId: {tenant}
```
**Response**:
```json
{
"totalFilteredRecords": 3,
"pageItems": [
{
"clientId": 1,
"chargeId": 101,
"name": "Processing Fee",
"dueDate": [2025, 1, 15],
"chargeTimeType": {
"id": 2,
"code": "chargeTimeType.specifiedDueDate",
"value": "Specified due date"
},
"chargeCalculationType": {
"id": 1,
"code": "chargeCalculationType.flat",
"value": "Flat"
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"amount": 50.00,
"amountPaid": 0.00,
"amountWaived": 0.00,
"amountWrittenOff": 0.00,
"amountOutstanding": 50.00,
"penalty": false,
"isActive": true,
"isChargePaid": false,
"isChargeWaived": false,
"paid": false,
"waived": false
},
{
"clientId": 1,
"chargeId": 102,
"name": "Annual Maintenance Fee",
"dueDate": [2024, 12, 1],
"chargeTimeType": {
"id": 1,
"code": "chargeTimeType.annual",
"value": "Annual"
},
"chargeCalculationType": {
"id": 1,
"code": "chargeCalculationType.flat",
"value": "Flat"
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"amount": 25.00,
"amountPaid": 25.00,
"amountWaived": 0.00,
"amountWrittenOff": 0.00,
"amountOutstanding": 0.00,
"penalty": false,
"isActive": false,
"isChargePaid": true,
"isChargeWaived": false,
"paid": true,
"waived": false
}
]
}
```
**Kotlin DTO**: Uses `Page<Charge>` from `core/model/entity/`
**Status**: Implemented in `ClientChargeService`
---
### 2. Get Loan Charges
**Endpoint**: `GET /loans/{loanId}/charges`
**Purpose**: Fetches charges for a specific loan account
**Request**:
```
Headers:
Authorization: Basic {token}
Fineract-Platform-TenantId: {tenant}
```
**Response**:
```json
[
{
"chargeId": 201,
"name": "Disbursement Fee",
"dueDate": [2024, 11, 1],
"chargeTimeType": {
"id": 1,
"code": "chargeTimeType.disbursement",
"value": "Disbursement"
},
"chargeCalculationType": {
"id": 2,
"code": "chargeCalculationType.percentageOfAmount",
"value": "% Amount"
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"amount": 100.00,
"amountPaid": 100.00,
"amountWaived": 0.00,
"amountWrittenOff": 0.00,
"amountOutstanding": 0.00,
"penalty": false,
"isActive": false,
"isChargePaid": true,
"paid": true,
"waived": false
},
{
"chargeId": 202,
"name": "Late Payment Penalty",
"dueDate": [2025, 1, 1],
"chargeTimeType": {
"id": 9,
"code": "chargeTimeType.overdueInstallment",
"value": "Overdue Installment"
},
"chargeCalculationType": {
"id": 1,
"code": "chargeCalculationType.flat",
"value": "Flat"
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"amount": 15.00,
"amountPaid": 0.00,
"amountWaived": 0.00,
"amountWrittenOff": 0.00,
"amountOutstanding": 15.00,
"penalty": true,
"isActive": true,
"isChargePaid": false,
"paid": false,
"waived": false
}
]
```
**Kotlin DTO**: Uses `List<Charge>` from `core/model/entity/`
**Status**: Implemented in `ClientChargeService`
---
### 3. Get Savings Account Charges
**Endpoint**: `GET /savingsaccounts/{accountId}/charges`
**Purpose**: Fetches charges for a specific savings account
**Request**:
```
Headers:
Authorization: Basic {token}
Fineract-Platform-TenantId: {tenant}
```
**Response**:
```json
[
{
"chargeId": 301,
"name": "Account Opening Fee",
"dueDate": [2024, 6, 1],
"chargeTimeType": {
"id": 1,
"code": "chargeTimeType.savingsActivation",
"value": "Savings Activation"
},
"chargeCalculationType": {
"id": 1,
"code": "chargeCalculationType.flat",
"value": "Flat"
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"amount": 10.00,
"amountPaid": 10.00,
"amountWaived": 0.00,
"amountWrittenOff": 0.00,
"amountOutstanding": 0.00,
"penalty": false,
"isActive": false,
"isChargePaid": true,
"paid": true,
"waived": false
},
{
"chargeId": 302,
"name": "Monthly Service Fee",
"dueDate": [2025, 1, 31],
"chargeTimeType": {
"id": 3,
"code": "chargeTimeType.monthly",
"value": "Monthly Fee"
},
"chargeCalculationType": {
"id": 1,
"code": "chargeCalculationType.flat",
"value": "Flat"
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"amount": 5.00,
"amountPaid": 0.00,
"amountWaived": 0.00,
"amountWrittenOff": 0.00,
"amountOutstanding": 5.00,
"penalty": false,
"isActive": true,
"isChargePaid": false,
"paid": false,
"waived": false
}
]
```
**Kotlin DTO**: Uses `List<Charge>` from `core/model/entity/`
**Status**: Implemented in `ClientChargeService`
---
### 4. Get Share Account Details (includes Charges)
**Endpoint**: `GET /shareaccounts/{accountId}`
**Purpose**: Fetches share account details which includes associated charges
**Request**:
```
Headers:
Authorization: Basic {token}
Fineract-Platform-TenantId: {tenant}
```
**Response**:
```json
{
"id": 1,
"accountNo": "000000001",
"clientId": 1,
"productId": 1,
"productName": "Share Product",
"status": {
"id": 300,
"code": "shareAccountStatusType.active",
"value": "Active"
},
"charges": [
{
"chargeId": 401,
"name": "Share Purchase Fee",
"dueDate": [2024, 8, 1],
"chargeTimeType": {
"id": 13,
"code": "chargeTimeType.sharesPurchase",
"value": "Share Purchase"
},
"chargeCalculationType": {
"id": 1,
"code": "chargeCalculationType.flat",
"value": "Flat"
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"amount": 20.00,
"amountPaid": 20.00,
"amountWaived": 0.00,
"amountWrittenOff": 0.00,
"amountOutstanding": 0.00,
"penalty": false,
"isActive": false,
"isChargePaid": true,
"paid": true,
"waived": false
}
]
}
```
**Kotlin DTO**: Uses `ShareAccountDetails` which contains `List<Charge>`
**Status**: Implemented in `ShareAccountService`
---
## Kotlin DTOs
### Charge
```kotlin
// Location: core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/Charge.kt
@Serializable
@Parcelize
data class Charge(
val clientId: Int? = null,
val chargeId: Int? = null,
val name: String? = null,
val dueDate: ArrayList<Int?> = arrayListOf(),
val chargeTimeType: ChargeTimeType? = null,
val chargeCalculationType: ChargeCalculationType? = null,
val currency: Currency? = null,
val amount: Double = 0.0,
val amountPaid: Double = 0.0,
val amountWaived: Double = 0.0,
val amountWrittenOff: Double = 0.0,
val amountOutstanding: Double = 0.0,
val penalty: Boolean = false,
val isActive: Boolean = false,
val isChargePaid: Boolean = false,
val isChargeWaived: Boolean = false,
val paid: Boolean = false,
val waived: Boolean = false,
) : Parcelable
```
### ChargeTimeType
```kotlin
// Location: core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/ChargeTimeType.kt
@Serializable
@Parcelize
data class ChargeTimeType(
val id: Int = 0,
val code: String? = null,
val value: String? = null,
) : Parcelable
```
### ChargeCalculationType
```kotlin
// Location: core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/ChargeCalculationType.kt
@Parcelize
@Serializable
data class ChargeCalculationType(
val id: Int = 0,
val code: String? = null,
val value: String? = null,
) : Parcelable
```
### Currency
```kotlin
// Location: core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/Currency.kt
@Serializable
@Parcelize
data class Currency(
val code: String? = null,
val name: String? = null,
val decimalPlaces: Int = 0,
val inMultiplesOf: Double = 0.0,
val displaySymbol: String? = null,
val nameCode: String? = null,
val displayLabel: String? = null,
) : Parcelable
```
### Page
```kotlin
// Location: core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/Page.kt
@Serializable
data class Page<T>(
val totalFilteredRecords: Int = 0,
val pageItems: List<T> = emptyList(),
)
```
### ChargeType (Enum)
```kotlin
// Location: core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/enums/ChargeType.kt
enum class ChargeType(val type: String) {
CLIENT("clients"),
SAVINGS("savingsaccounts"),
LOAN("loans"),
SHARE("shareaccounts"),
}
```
---
## Kotlin Implementation
### Service (ClientChargeService.kt)
```kotlin
// Location: core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/ClientChargeService.kt
interface ClientChargeService {
@GET(ApiEndPoints.CLIENTS + "/{clientId}/charges")
fun getClientChargeList(@Path("clientId") clientId: Long): Flow<Page<Charge>>
@GET("{chargeType}/{chargeTypeId}/charges")
fun getChargeList(
@Path("chargeType") chargeType: String,
@Path("chargeTypeId") chargeTypeId: Long,
): Flow<List<Charge>>
}
```
### Repository Interface (ClientChargeRepository.kt)
```kotlin
// Location: core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repository/ClientChargeRepository.kt
interface ClientChargeRepository {
fun getCharges(clientId: Long): Flow<DataState<Page<Charge>>>
fun getLoanOrSavingsCharges(chargeType: ChargeType, chargeTypeId: Long): Flow<DataState<List<Charge>>>
fun clientLocalCharges(): Flow<DataState<Page<Charge>>>
suspend fun syncCharges(charges: Page<Charge>?): DataState<Page<Charge>?>
fun getShareAccountCharges(shareAccountId: Long): Flow<DataState<List<Charge>>>
}
```
### Repository Implementation (ClientChargeRepositoryImp.kt)
```kotlin
// Location: core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/ClientChargeRepositoryImp.kt
class ClientChargeRepositoryImp(
private val dataManager: DataManager,
private val ioDispatcher: CoroutineDispatcher,
) : ClientChargeRepository {
override fun getCharges(clientId: Long): Flow<DataState<Page<Charge>>> {
return dataManager.clientChargeApi.getClientChargeList(clientId)
.map { response -> DataState.Success(response) }
.catch { exception -> DataState.Error(exception, exception.message) }
.flowOn(ioDispatcher)
}
override fun getLoanOrSavingsCharges(
chargeType: ChargeType,
chargeTypeId: Long
): Flow<DataState<List<Charge>>> {
return dataManager.clientChargeApi.getChargeList(chargeType.type, chargeTypeId)
.map { response -> DataState.Success(response) }
.catch { exception -> DataState.Error(exception, exception.message) }
.flowOn(ioDispatcher)
}
override fun getShareAccountCharges(shareAccountId: Long): Flow<DataState<List<Charge>>> {
return dataManager.shareAccountApi.getShareAccountDetails(shareAccountId)
.map { response -> DataState.Success(response.charges) }
.catch { exception -> DataState.Error(exception, exception.message) }
.flowOn(ioDispatcher)
}
// ... other methods
}
```
---
## API Summary
| Endpoint | Method | Service | Repository | Response Type | Status |
|----------|--------|---------|------------|---------------|--------|
| `/clients/{id}/charges` | GET | ClientChargeService | ClientChargeRepository | `Page<Charge>` | Implemented |
| `/loans/{id}/charges` | GET | ClientChargeService | ClientChargeRepository | `List<Charge>` | Implemented |
| `/savingsaccounts/{id}/charges` | GET | ClientChargeService | ClientChargeRepository | `List<Charge>` | Implemented |
| `/shareaccounts/{id}` | GET | ShareAccountService | ClientChargeRepository | `ShareAccountDetails` (contains charges) | Implemented |
---
## Notes
- **Client Charges**: Return paginated response with `Page<Charge>` wrapper containing `totalFilteredRecords` and `pageItems`
- **Loan/Savings Charges**: Return direct `List<Charge>` without pagination wrapper
- **Share Charges**: Retrieved via Share Account Details endpoint, extracted from `response.charges`
- **Currency Formatting**: Use `CurrencyFormatter.format()` with currency code from charge
- **Date Handling**: Due dates are arrays `[year, month, day]`, use `DateHelper.getDateAsString()` to format
- **Charge Status**: Check `isChargePaid` or `paid` boolean to determine payment status
- **Empty Due Date**: Handle empty `dueDate` array by showing "-" as fallback
---
## Error Responses
| Status Code | Description | Handling |
|-------------|-------------|----------|
| 401 | Unauthorized | Redirect to login |
| 403 | Forbidden | Show permission error |
| 404 | Account not found | Show "Account not found" error |
| 500 | Server error | Show generic server error with retry |
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Updated with complete DTOs, repository implementation, and detailed response examples from codebase analysis |
| 2025-12-29 | Initial API documentation |

View File

@ -1,395 +0,0 @@
# Client Charges - Feature Specification
> **Purpose**: Display and manage charges for clients, loans, savings, and share accounts
> **User Value**: View all pending and paid charges, track due dates, and access payment details
> **Last Updated**: 2025-12-29
---
## 1. Overview
### 1.1 Feature Summary
The Client Charges feature allows users to view charges associated with their client account, loan accounts, savings accounts, and share accounts. It displays a list of charges with status indicators (paid/unpaid), amounts, due dates, and provides navigation to detailed charge information. Users can see charge breakdowns including due amount, paid amount, waived amount, and outstanding balance.
### 1.2 User Stories
- As a user, I want to view all charges on my client account so I can track fees and payments
- As a user, I want to view charges on my loan account so I can see loan-related fees
- As a user, I want to view charges on my savings account so I can track savings-related fees
- As a user, I want to view charges on my share account so I can see share-related fees
- As a user, I want to see which charges are paid vs outstanding so I can prioritize payments
- As a user, I want to view charge details so I can understand the breakdown of amounts
- As a user, I want to see due dates so I can plan my payments accordingly
---
## 2. Screen Layout
### 2.1 Charges List Screen - ASCII Mockup
```
+------------------------------------------+
| [<] Client Charges | <- TopBar (title varies by type)
+------------------------------------------+
| |
| +------------------------------------+ |
| | [DB] Loan Processing Fee > | |
| | ChargeId: 123 | |
| | 2025-01-15 | |
| | Due | |
| | $150.00 | |
| +------------------------------------+ |
| |
| +------------------------------------+ |
| | [OK] Annual Service Fee > | |
| | ChargeId: 456 | |
| | 2024-12-01 | |
| | Paid | |
| | $50.00 | |
| +------------------------------------+ |
| |
| +------------------------------------+ |
| | [DB] Late Payment Penalty > | |
| | ChargeId: 789 | |
| | 2025-02-01 | |
| | Due | |
| | $25.00 | |
| +------------------------------------+ |
| |
+------------------------------------------+
| Powered by Mifos |
+------------------------------------------+
Legend:
[<] = Back navigation
[DB] = Database warning icon (unpaid)
[OK] = Database checkmark icon (paid)
> = Chevron right (navigate to details)
```
### 2.2 Charge Details Screen - ASCII Mockup
```
+------------------------------------------+
| [<] Charge Details | <- TopBar
+------------------------------------------+
| |
| +------------------------------------+ |
| | Fee Title | Loan Processing Fee | |
| +------------------------------------+ |
| | Date | 2025-01-15 | |
| +------------------------------------+ |
| | Due | $150.00 | |
| +------------------------------------+ |
| | Paid | $75.00 | |
| +------------------------------------+ |
| | Waived | $0.00 | |
| +------------------------------------+ |
| | Outstanding | $75.00 | |
| +------------------------------------+ |
| |
| +------------------------------------+ |
| | [PAY OUTSTANDING] | | <- For unpaid charges
| +------------------------------------+ |
| |
| Partial amount paid on: 2025-01-10 |
| |
+------------------------------------------+
| Powered by Mifos |
+------------------------------------------+
--- OR (for fully paid charges) ---
+------------------------------------------+
| [<] Charge Details |
+------------------------------------------+
| |
| +------------------------------------+ |
| | Fee Title | Annual Service Fee | |
| +------------------------------------+ |
| | Date | 2024-12-01 | |
| +------------------------------------+ |
| | Due | $50.00 | |
| +------------------------------------+ |
| | Paid | $50.00 | |
| +------------------------------------+ |
| | Waived | $0.00 | |
| +------------------------------------+ |
| | Outstanding | $0.00 | |
| +------------------------------------+ |
| |
| This charge has been successfully paid |
| |
| [SUCCESS ICON] |
| |
| Ref No: CHG-456 |
| Paid on: 2024-12-01 |
| |
+------------------------------------------+
| Powered by Mifos |
+------------------------------------------+
```
### 2.3 Sections Table
| # | Section | Description | API | Priority |
|---|---------|-------------|-----|----------|
| 1 | TopBar | Title varies: Client/Loan/Savings/Share Charges | - | P0 |
| 2 | Charge List | Scrollable list of charge items | clients/{id}/charges, loans/{id}/charges, savingsaccounts/{id}/charges | P0 |
| 3 | Charge Item | Icon, name, charge ID, date, status, amount | - | P0 |
| 4 | Empty State | "No charges" message when list is empty | - | P0 |
| 5 | Error State | Error message with retry button | - | P0 |
| 6 | Network State | No connection message | - | P0 |
| 7 | Details Card | Key-value pairs for charge details | - | P0 |
| 8 | Payment Section | Pay button or success confirmation | - | P1 |
| 9 | Footer | Powered by Mifos | - | P2 |
---
## 3. User Interactions
| Action | Trigger | Result | API Call |
|--------|---------|--------|----------|
| Navigate back | Tap back arrow | Return to previous screen | - |
| View charge details | Tap charge item | Navigate to ChargeDetailScreen | - |
| Retry loading | Tap retry button | Reload charges | clients/{id}/charges |
| Pay outstanding | Tap pay button | (Future) Payment flow | - |
| Pull to refresh | Swipe down | Reload charge list | clients/{id}/charges |
---
## 4. State Model
### 4.1 Charges List Screen
```kotlin
/**
* Represents the UI state of the Client Charges screen.
*/
data class ClientChargeState(
val networkStatus: Boolean = false,
val clientId: Long,
val chargeType: ChargeType, // CLIENT, LOAN, SAVINGS, SHARE
val chargeTypeId: Long?, // Account ID for LOAN/SAVINGS/SHARE
val isOnline: Boolean,
val isEmpty: Boolean = false,
val topBarTitleResId: StringResource, // Dynamic based on chargeType
val charges: List<Charge> = emptyList(),
val dialogState: DialogState? = null,
val uiState: ScreenUiState? = ScreenUiState.Loading,
) {
sealed interface DialogState {
data class Error(val message: String) : DialogState
}
}
/**
* UI events emitted from the ViewModel to be handled by the UI layer.
*/
sealed interface ClientChargeEvent {
data class ShowToast(val message: String) : ClientChargeEvent
data object Navigate : ClientChargeEvent
data class OnChargeClick(val charge: Charge) : ClientChargeEvent
}
/**
* Actions dispatched from the UI or internal processes.
*/
sealed interface ClientChargeAction {
data object RefreshCharges : ClientChargeAction
data object OnNavigate : ClientChargeAction
data object OnDismissDialog : ClientChargeAction
data class OnChargeClick(val charge: Charge) : ClientChargeAction
data class ReceiveNetworkResult(val isOnline: Boolean) : ClientChargeAction
data object Retry : ClientChargeAction
sealed class Internal : ClientChargeAction {
data class ReceiveLoanOrSavingsChargesResult(
val result: DataState<List<Charge>>
) : Internal()
data class ReceiveClientChargesResult(
val result: DataState<Page<Charge>>
) : Internal()
data class ReceiveShareChargesResult(
val result: DataState<List<Charge>>
) : Internal()
}
}
/**
* ChargeType determines which endpoint to call and what title to show.
*/
enum class ChargeType(val type: String) {
CLIENT("clients"),
SAVINGS("savingsaccounts"),
LOAN("loans"),
SHARE("shareaccounts"),
}
```
### 4.2 Charge Details Screen
```kotlin
/**
* Represents the state of the Charge Details Screen.
*/
data class ChargeDetailsState(
val details: Map<StringResource, String> = emptyMap(), // fee_title, date, due, paid, waived, outstanding
val isPaid: Boolean = false,
val refNo: String = "",
val paidOn: String = "",
)
/**
* Events for the Charge Details Screen.
*/
sealed interface ChargeDetailsEvent {
data object NavigateBack : ChargeDetailsEvent
}
/**
* Actions for the Charge Details Screen.
*/
sealed interface ChargeDetailsAction {
data object NavigateBack : ChargeDetailsAction
data object PayOutStanding : ChargeDetailsAction
}
```
---
## 5. API Requirements
| Endpoint | Method | Purpose | Status |
|----------|--------|---------|--------|
| `/clients/{clientId}/charges` | GET | Get client-level charges (paginated) | Implemented |
| `/loans/{loanId}/charges` | GET | Get loan account charges | Implemented |
| `/savingsaccounts/{savingsId}/charges` | GET | Get savings account charges | Implemented |
| `/shareaccounts/{shareId}` | GET | Get share account details (includes charges) | Implemented |
---
## 6. Edge Cases & Error Handling
| Scenario | Behavior | UI Feedback |
|----------|----------|-------------|
| No internet | Set uiState to Network | "No internet connection" with retry |
| Empty charge list | Set uiState to Empty | "No charges found" with warning icon |
| API error | Set uiState to Error | Server error message with retry |
| Invalid charge type | Default to CLIENT | - |
| Missing due date | Show "-" for date | Safe date string handling |
| Zero amounts | Display as "0.00" | Formatted currency display |
| Network restored | Automatically reload | Triggered by network monitor |
| IOException | Show network state | "No internet connection" |
| Other exceptions | Show error state | "Server error" message |
---
## 7. Components
| Component | Props | Reusable? |
|-----------|-------|-----------|
| ClientChargeItem | charge: Charge, onChargeClick: () -> Unit | Yes |
| MifosDetailsCard | keyValuePairs: Map<StringResource, String> | Yes (core:ui) |
| ChargeDetailsPaidComponent | refNo: String, paidOn: String | No |
| ChargeDetailsUnPaidComponent | amountPaidOn: String, onPayOutStanding: () -> Unit | No |
| MifosElevatedScaffold | topBarTitle, onNavigateBack, bottomBar, content | Yes (core:designsystem) |
| MifosErrorComponent | isNetworkConnected, isRetryEnabled, message, onRetry | Yes (core:ui) |
| EmptyDataView | image, error | Yes (core:ui) |
| MifosProgressIndicator | - | Yes (core:designsystem) |
---
## 8. Navigation
### 8.1 Routes
```kotlin
// Charges List Route
@Serializable
data class ClientChargesRoute(
val chargeType: String, // "CLIENT", "LOAN", "SAVINGS", "SHARE"
val chargeTypeId: Long? = null, // Required for LOAN/SAVINGS/SHARE
)
// Charge Details Route
@Serializable
data class ChargesDetailsRoute(
val title: String = "",
val date: String = "",
val due: String = "",
val paid: String = "",
val waived: String = "",
val outstanding: String = "",
val refNo: String = "",
val paidOn: String = "",
val isPaid: Boolean = false,
)
```
### 8.2 Navigation Flow
```
Home Dashboard
|
v
[Services Grid] -> "Charges" card
|
v
Client Charges Screen (chargeType = CLIENT)
|
v (tap charge item)
Charge Details Screen
--- OR ---
Loan Account Details
|
v
[View Charges] action
|
v
Loan Charges Screen (chargeType = LOAN, chargeTypeId = loanId)
|
v (tap charge item)
Charge Details Screen
```
---
## 9. Dependencies
### 9.1 Module Dependencies
```kotlin
// feature/client-charge/build.gradle.kts
plugins {
alias(libs.plugins.convention.cmp.feature)
}
dependencies {
implementation(projects.core.data)
implementation(projects.core.model)
implementation(projects.core.ui)
implementation(projects.core.designsystem)
implementation(projects.core.common)
}
```
### 9.2 Repository Dependency
```kotlin
// Koin Module - ChargeModule.kt
val chargeModule = module {
viewModelOf(::ClientChargeViewModel)
viewModelOf(::ChargeDetailsViewModel)
}
```
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Updated specification with detailed ASCII mockups, complete state models from implementation, navigation routes, and component details |
| 2025-12-29 | Initial spec from codebase analysis |

View File

@ -1,85 +0,0 @@
# Client Charge - Implementation Status
> **Last Updated**: 2025-12-29
> **Overall Status**: ✅ Done
---
## Implementation Checklist
- [x] SPEC.md created
- [x] API.md created
- [x] Network: Services exist (ClientChargeService)
- [x] Data: Repository exists (ClientChargeRepository)
- [x] Feature: ViewModels + Screens
- [x] Navigation: Routes registered
- [x] DI: Modules registered
- [x] STATUS.md updated
---
## Layer Status
| Layer | Status | Files |
|-------|--------|-------|
| Network | ✅ | ClientChargeService.kt |
| Data | ✅ | ClientChargeRepository.kt, ClientChargeRepositoryImp.kt |
| Feature | ✅ | ClientChargeViewModel.kt, ClientChargeScreen.kt, ChargeDetailsViewModel.kt, ChargeDetailScreen.kt |
| DI | ✅ | ChargeModule.kt |
| Navigation | ✅ | ClientChargesNavGraph.kt |
| Components | ✅ | ClientChargeItem.kt |
---
## Files
### Network Layer
- `core/network/services/ClientChargeService.kt`
### Data Layer
- `core/data/repository/ClientChargeRepository.kt`
- `core/data/repositoryImpl/ClientChargeRepositoryImp.kt`
### Feature Layer - Charges List
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/charges/ClientChargeViewModel.kt`
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/charges/ClientChargeScreen.kt`
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/charges/ClientChargeRoute.kt`
### Feature Layer - Charge Details
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/chargeDetails/ChargeDetailsViewModel.kt`
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/chargeDetails/ChargeDetailScreen.kt`
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/chargeDetails/ChargeDetailsRoute.kt`
### Components
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/components/ClientChargeItem.kt`
### DI Layer
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/di/ChargeModule.kt`
### Navigation Layer
- `feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/navigation/ClientChargesNavGraph.kt`
---
## Charge Types Supported
| Type | Endpoint | Description |
|------|----------|-------------|
| CLIENT | `/clients/{id}/charges` | Client-level charges |
| LOAN | `/loans/{id}/charges` | Loan account charges |
| SAVINGS | `/savingsaccounts/{id}/charges` | Savings account charges |
| SHARE | `/shareaccounts/{id}` | Share account charges (via account details) |
---
## Gaps
None identified.
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-29 | Initial status documentation |

View File

@ -1,69 +0,0 @@
# Client Charges Feature - Figma Links
> **Feature**: Client Charges (Smart Charges Hub)
> **Status**: Pending Design Export
> **Last Updated**: 2025-01-04
---
## Figma Design Links
After generating designs using AI tools (Stitch/Figma), paste the links below:
### Main Screens
| Screen | Figma Link | Status |
|--------|------------|--------|
| Smart Dashboard | `[Paste link here]` | Pending |
| Calendar View | `[Paste link here]` | Pending |
| Charge Detail | `[Paste link here]` | Pending |
| Autopay Setup - Step 1 | `[Paste link here]` | Pending |
| Autopay Setup - Step 2 | `[Paste link here]` | Pending |
| Autopay Setup - Step 3 | `[Paste link here]` | Pending |
| Split Payment | `[Paste link here]` | Pending |
| Payment Success | `[Paste link here]` | Pending |
| Charge Insights | `[Paste link here]` | Pending |
| Waiver Request | `[Paste link here]` | Pending |
| Empty State | `[Paste link here]` | Pending |
### Component Library
| Component | Figma Link | Status |
|-----------|------------|--------|
| Balance Card | `[Paste link here]` | Pending |
| Streak Banner | `[Paste link here]` | Pending |
| Quick Action Grid | `[Paste link here]` | Pending |
| Charge Card | `[Paste link here]` | Pending |
| Status Chip | `[Paste link here]` | Pending |
| Calendar Day | `[Paste link here]` | Pending |
| Plan Card | `[Paste link here]` | Pending |
| Progress Bar | `[Paste link here]` | Pending |
| Timeline | `[Paste link here]` | Pending |
| AI Tip Card | `[Paste link here]` | Pending |
### Dark Mode Variants
| Screen | Figma Link | Status |
|--------|------------|--------|
| Smart Dashboard (Dark) | `[Paste link here]` | Pending |
| Charge Detail (Dark) | `[Paste link here]` | Pending |
| Calendar View (Dark) | `[Paste link here]` | Pending |
---
## Export Checklist
- [ ] Export all screens at 1x, 2x, 3x
- [ ] Export component assets as SVG
- [ ] Export Lottie animations (streak flame, confetti)
- [ ] Document color variables
- [ ] Create prototype connections
- [ ] Add interaction annotations
- [ ] Review accessibility contrast
- [ ] Verify dark mode mappings
---
## Notes
_Add any design notes, feedback, or revision history here._

View File

@ -1,549 +0,0 @@
# Client Charges Feature - AI Design Tool Prompts
> **Generated from**: MOCKUP.md v2.0
> **Design Pattern**: Smart Charges Hub
> **Primary Gradient**: #667EEA (Purple) -> #764BA2 (Deep Purple)
> **Generated**: 2025-01-04
---
## Google Stitch Prompts
### Prompt 1: Smart Charges Dashboard
```
Create a Smart Charges Dashboard screen for a fintech banking app.
Design specifications:
- Material Design 3 with 2025 fintech patterns
- Primary gradient: #667EEA to #764BA2
- Gamified payment streak integration
Header:
- Back button, "My Charges" title
- Calendar icon, Settings icon
Outstanding Balance Card (Gradient):
- Background: Gradient #667EEA to #764BA2
- Large amount: "$225.00" (36sp bold white)
- Label: "OUTSTANDING BALANCE"
- Three stat boxes below:
- Total: $500.00
- Paid: $250.00 (green indicator)
- Waived: $25.00 (yellow indicator)
Payment Streak Banner:
- Fire icon with "On-Time Streak: 5 payments"
- Progress bar: Showing 5/10 to next reward
- Text: "Next reward at 10!"
- Flame animation on icon
Quick Actions Row:
- 4 icon buttons in grid:
- Pay All (credit card icon)
- Autopay Setup (refresh icon)
- Calendar View (calendar icon)
- Insights (chart icon)
- Each: 56dp square, icon + label
Filter Tabs:
- Horizontal scroll: All, Loan, Savings, Share
- Selected tab underlined with gradient
Due Soon Section:
- Section header: "DUE SOON (2)" with "View" link
- Charge cards with urgency indicators
Charge Card (Due Soon):
- Left icon: Document with red status dot
- Title: "Loan Processing Fee"
- Account: "LOAN-001234"
- Due: "Tomorrow" with "$150.00 outstanding"
- Status chips: "PENALTY", "75% paid", "Due in 1 day"
- Action buttons: "Pay $150.00", "Split Payment"
- Background: White, shadow, 20dp radius
Recently Paid Section:
- Section header: "RECENTLY PAID (2)"
- Compact paid charge cards with green checkmark
- "+5 pts earned" badge
Style: Gamified payments, urgency indicators, quick actions
```
### Prompt 2: Due Date Calendar View
```
Create a Payment Calendar screen for viewing charge due dates in a fintech app.
Design specifications:
- Material Design 3 with calendar patterns
- Color-coded due dates
Header:
- Back button, "Payment Calendar" title
Calendar Component:
- Month navigation: "< January 2025 >"
- Week day headers: Mo Tu We Th Fr Sa Su
- Date grid with indicators:
- Red dot: Overdue/Penalty
- Yellow dot: Due Soon
- Green dot: Upcoming
- Checkmark: Paid
- Amount shown on relevant dates: "$150", "$50"
- Selected date highlighted with gradient circle
Legend:
- Color key: Overdue (red), Due Soon (yellow), Upcoming (green), Paid (check)
Selected Date Section:
- Date header: "JANUARY 15 - DUE"
- Charge cards for that date:
- Loan Processing Fee, $150.00
- "Pay Now" button
AI Tip Card:
- Light bulb icon
- "Based on your cash flow, the best day to pay the $150 charge is January 10th when your balance is highest."
- Action button: "Schedule Payment for Jan 10"
Monthly Summary (collapsible):
- Total due this month: $200
- Paid so far: $0
- Upcoming: $200
Style: Visual calendar, smart scheduling, AI recommendations
```
### Prompt 3: Charge Detail Screen
```
Create a Charge Detail screen with comprehensive payment options for a fintech app.
Design specifications:
- Material Design 3 with detailed charge information
- Multiple payment action options
Header (Gradient):
- Background: Gradient #667EEA to #764BA2
- Back button, "Charge Details" title, More menu
- Large icon with document
- Charge name: "LOAN PROCESSING FEE"
- Account: "Loan Account: LOAN-001234"
- Outstanding: "$150.00" (36sp bold white)
- Status chips: "PENALTY", "Due Tomorrow"
Amount Breakdown Card:
- Title: "AMOUNT BREAKDOWN"
- Rows with values:
- Due Amount: $150.00
- Amount Paid: $75.00 (green)
- Amount Waived: $0.00 (yellow)
- Outstanding: $75.00 (red)
- Payment Progress bar: 50% filled
Charge Details Card:
- Title: "CHARGE DETAILS"
- Info rows:
- Charge ID: #123
- Due Date: Jan 15, 2025
- Calculation Type: Flat Rate
- Charge Time Type: On Disbursement
- Currency: USD
- Is Penalty: Yes (red badge)
Payment History Timeline:
- Title: "PAYMENT HISTORY"
- Timeline entries:
- Jan 10: Partial Payment, $75.00 paid (green)
- Dec 28: Charge Created, $150.00 applied
Payment Options Section:
- Title: "PAYMENT OPTIONS"
- Primary button: "Pay Full Amount ($75.00)" (gradient)
- Secondary options:
- "Split into 2 Payments of $37.50"
- "Set Up Autopay for Future"
- "Request Waiver"
Style: Comprehensive info, multiple payment paths, clear history
```
### Prompt 4: Autopay Setup Flow
```
Create an Autopay Setup wizard for charges in a fintech app.
Design specifications:
- Material Design 3 with step wizard
- 3-step setup process
Step 1: Select Charges
Header:
- Back button, "Set Up Autopay" title
- Step indicator: "Step 1 of 3" with 33% progress bar
Intro:
- Refresh icon
- Title: "Set Up Automatic Payments"
- Subtitle: "Never miss a payment. Autopay will automatically pay charges when due."
Charge Type Selection:
- Title: "SELECT CHARGES TO AUTOPAY"
- Checkbox cards:
- All Future Loan Charges (checked)
- "Includes: Processing fees, late fees, penalties"
- "Estimated: ~$50-200/month"
- All Future Savings Charges (checked)
- "Includes: Maintenance fees, service charges"
- "Estimated: ~$25/month"
- All Future Client Charges (unchecked)
- "Includes: Annual fees, document fees"
- "Estimated: ~$100/year"
Continue Button: "Continue to Select Account"
Step 2: Select Account
- Progress: 66%
- Title: "PAY FROM ACCOUNT"
- Account cards (radio selection):
- Primary Savings ****4521 (selected, recommended)
- Available: $8,200.00
- "Recommended - Highest balance"
- Emergency Fund ****7832
- Available: $2,500.00
Payment Timing:
- Radio options:
- On Due Date (Recommended, selected)
- 3 Days Before Due Date
- 7 Days Before Due Date
Low Balance Protection:
- Checkbox: "Skip autopay if account balance is below $500"
- Subtitle: "You'll be notified to pay manually"
Continue Button: "Continue to Confirm"
Step 3: Confirmation
- Progress: 100%
- Summary Card:
- Charges: Loan + Savings
- Account: Savings ****4521
- Timing: On Due Date
- Protection: Skip if < $500
Benefits List:
- Never miss a payment
- Protect your payment streak
- Avoid late fees and penalties
- Earn autopay bonus points
Email Notice:
- "You'll receive email confirmation and reminders 24 hours before each autopay"
Enable Button: "Enable Autopay" (gradient)
Style: Guided setup, clear benefits, protection options
```
### Prompt 5: Split Payment Flow
```
Create a Split Payment screen for breaking charges into installments in a fintech app.
Design specifications:
- Material Design 3 with installment patterns
- Clear payment plan visualization
Header:
- Back button, "Split Payment" title
Charge Context:
- Document icon
- "Loan Processing Fee"
- "Original Amount: $150.00"
Payment Plan Selection:
- Title: "CHOOSE PAYMENT PLAN"
Plan Cards (radio selection):
Plan 1 - 2 Payments (selected):
- "$75.00 x 2"
- Timeline visualization: Jan 15 -> Feb 15
- Amounts shown: $75.00 each
- Badge: "No extra fees, Recommended"
- Gradient border when selected
Plan 2 - 3 Payments:
- "$50.00 x 3"
- Timeline: Jan 15 -> Feb 15 -> Mar 15
- "+$5.00 split fee" warning
Plan 3 - 4 Payments:
- "$37.50 x 4"
- Timeline: Jan 15 - Apr 15 (monthly)
- "+$10.00 split fee"
Payment Summary:
- Charge Amount: $150.00
- Split Fee: $0.00
- Total: $150.00
- First Payment Due: Jan 15, 2025
Account Selector:
- Credit card icon
- "Pay From: Savings ****4521"
- "Change >" link
Confirm Button:
- "Confirm Split Payment" (gradient)
Terms:
- Small text about split payment agreement
Style: Clear plan comparison, timeline visualization, fee transparency
```
### Prompt 6: Payment Success Screen
```
Create a Payment Success screen with streak update for a fintech app.
Design specifications:
- Material Design 3 with celebration patterns
- Gamification integration
Success Header:
- Large checkmark with animated circle
- Confetti animation background
- "Payment Success!" text
Amount Display:
- "$75.00"
- "Loan Processing Fee"
Transaction Details Card:
- Reference: TXN-2025-001234
- Date: Jan 15, 2025
- From Account: Savings ****4521
- Status: Completed (green)
Streak Update Banner (Gradient):
- Fire icon
- "STREAK UPDATED!"
- "Your on-time payment streak is now 6!"
- Progress bar: 6/10 to reward
- "+10 points earned for on-time payment"
Action Buttons:
- Download Receipt
- Share Receipt
Back Button:
- "Back to Charges"
Style: Celebratory, gamified rewards, clear confirmation
```
---
## Figma MCP Prompts
### Prompt 1: Charges Dashboard Frame
```
Create a Figma frame for "Charges - Smart Dashboard" mobile screen (375x812px).
Components needed:
1. Header: Back button, title, calendar and settings icons
2. Outstanding Balance Card:
- Gradient background
- Large amount display
- Three stat boxes row
3. Payment Streak Banner:
- Fire icon with animation indicator
- Progress bar
- Reward text
4. Quick Actions Grid:
- 4 icon buttons: Pay All, Autopay, Calendar, Insights
- Auto-layout 2x2 or 1x4
5. Filter Tabs:
- Horizontal scroll
- Selected/unselected states
6. Charge Card Component (create variants):
- Due Soon (urgent styling)
- Paid (success styling)
- Overdue (error styling)
- Status chips
- Action buttons
7. Section Headers:
- Title with count badge
- View link
Design tokens:
- Primary: #667EEA
- Secondary: #764BA2
- Success: #00D09C
- Warning: #FFB800
- Error: #FF4757
```
### Prompt 2: Complete Charges Flow
```
Create a Figma prototype flow for Charges feature with these frames:
Frame 1: Smart Dashboard (main)
- Outstanding balance card
- Streak banner
- Quick actions
- Charge list
Frame 2: Calendar View
- Month calendar with indicators
- Selected date charges
- AI scheduling tip
Frame 3: Charge Detail
- Amount breakdown
- Charge info
- Payment history timeline
- Payment options
Frame 4-6: Autopay Setup Flow
- Step 1: Select charge types
- Step 2: Select account and timing
- Step 3: Confirmation
Frame 7: Split Payment
- Plan selection cards
- Timeline visualization
- Summary
Frame 8: Payment Success
- Celebration animation
- Streak update
- Receipt actions
Frame 9: Charge Insights
- Summary stats
- Charts
- Performance metrics
Prototype connections:
- Dashboard -> Detail via card tap
- Dashboard -> Calendar via quick action
- Pay button -> Success
- Autopay button -> Setup flow
Component variants:
- Charge card: due-soon/paid/overdue
- Status chip: penalty/autopay/due-date
- Plan card: selected/unselected
```
---
## Design Tokens
```json
{
"feature": "client-charge",
"version": "2.0",
"designPattern": "Smart Charges Hub",
"colors": {
"primary": "#667EEA",
"secondary": "#764BA2",
"success": "#00D09C",
"warning": "#FFB800",
"error": "#FF4757",
"surface": "#FFFFFF",
"background": "#F8F9FA"
},
"status": {
"paid": { "bg": "#00D09C15", "text": "#00D09C" },
"pending": { "bg": "#FFB80015", "text": "#FFB800" },
"overdue": { "bg": "#FF475715", "text": "#FF4757" },
"penalty": { "bg": "#FF475715", "text": "#FF4757" },
"autopay": { "bg": "#667EEA15", "text": "#667EEA" }
},
"components": {
"balanceCard": {
"height": "auto",
"padding": 20,
"radius": 24,
"statBoxWidth": 100
},
"streakBanner": {
"height": 80,
"progressHeight": 6,
"fireIconSize": 24
},
"chargeCard": {
"minHeight": 120,
"padding": 16,
"radius": 20,
"iconSize": 48,
"gap": 12
},
"statusChip": {
"height": 24,
"padding": 8,
"radius": 12,
"fontSize": 11
},
"calendarDay": {
"size": 40,
"indicatorSize": 8,
"selectedRadius": 20
},
"planCard": {
"padding": 16,
"radius": 16,
"timelineHeight": 4
},
"progressBar": {
"height": 6,
"radius": 3
}
},
"animation": {
"streakFlame": {
"duration": 2000,
"type": "flicker"
},
"confetti": {
"duration": 2000,
"particles": 20
},
"progressFill": {
"duration": 600,
"easing": "decelerate"
}
}
}
```
---
## Screen Checklist
| Screen | Stitch Prompt | Figma Prompt | Status |
|--------|---------------|--------------|--------|
| Smart Dashboard | 1 | 1, 2 | Ready |
| Calendar View | 2 | 2 | Ready |
| Charge Detail | 3 | 2 | Ready |
| Autopay Setup | 4 | 2 | Ready |
| Split Payment | 5 | 2 | Ready |
| Payment Success | 6 | 2 | Ready |
| Charge Insights | - | 2 | Pending |
| Waiver Request | - | - | Pending |
| Empty State | - | - | Pending |

View File

@ -1,283 +0,0 @@
{
"feature": "client-charge",
"version": "2.0",
"designPattern": "Smart Charges Hub",
"lastUpdated": "2025-01-04",
"colors": {
"primary": {
"default": "#667EEA",
"dark": "#5A6FD6"
},
"secondary": {
"default": "#764BA2",
"dark": "#6A4292"
},
"success": {
"default": "#00D09C",
"light": "#00D09C15"
},
"warning": {
"default": "#FFB800",
"light": "#FFB80015"
},
"error": {
"default": "#FF4757",
"light": "#FF475715"
},
"surface": {
"light": "#FFFFFF",
"dark": "#1A1F2E"
},
"background": {
"light": "#F8F9FA",
"dark": "#0D1117"
},
"text": {
"primary": {
"light": "#1F2937",
"dark": "#F0F6FC"
},
"secondary": {
"light": "#6B7280",
"dark": "#8B949E"
},
"onGradient": "#FFFFFF"
},
"divider": {
"light": "#E1E4E8",
"dark": "#30363D"
}
},
"gradients": {
"primary": {
"type": "linear",
"angle": 135,
"stops": [
{ "color": "#667EEA", "position": 0 },
{ "color": "#764BA2", "position": 100 }
]
},
"success": {
"type": "linear",
"angle": 135,
"stops": [
{ "color": "#00D09C", "position": 0 },
{ "color": "#38EF7D", "position": 100 }
]
},
"streak": {
"type": "linear",
"angle": 135,
"stops": [
{ "color": "#FF6B6B", "position": 0 },
{ "color": "#FFE66D", "position": 100 }
]
}
},
"typography": {
"fontFamily": {
"primary": "Inter",
"mono": "JetBrains Mono"
},
"styles": {
"h1": { "size": 28, "weight": 700, "lineHeight": 1.2 },
"h2": { "size": 24, "weight": 700, "lineHeight": 1.3 },
"amount": { "size": 36, "weight": 700, "lineHeight": 1.2 },
"amountMd": { "size": 28, "weight": 700, "lineHeight": 1.3 },
"subtitle": { "size": 16, "weight": 600, "lineHeight": 1.5 },
"body": { "size": 14, "weight": 400, "lineHeight": 1.5 },
"caption": { "size": 12, "weight": 400, "lineHeight": 1.4 },
"chip": { "size": 11, "weight": 600, "lineHeight": 1.4 }
}
},
"spacing": {
"xs": 4,
"sm": 8,
"md": 16,
"lg": 24,
"xl": 32,
"xxl": 48
},
"radius": {
"sm": 8,
"md": 12,
"lg": 16,
"xl": 20,
"xxl": 24,
"pill": 100
},
"elevation": {
"card": "0 2px 8px rgba(0,0,0,0.08)",
"cardHover": "0 4px 12px rgba(0,0,0,0.12)",
"modal": "0 8px 24px rgba(0,0,0,0.16)"
},
"status": {
"paid": {
"background": "#00D09C15",
"text": "#00D09C",
"icon": "checkmark"
},
"pending": {
"background": "#FFB80015",
"text": "#FFB800",
"icon": "clock"
},
"overdue": {
"background": "#FF475715",
"text": "#FF4757",
"icon": "alert"
},
"penalty": {
"background": "#FF475715",
"text": "#FF4757",
"icon": "warning"
},
"autopay": {
"background": "#667EEA15",
"text": "#667EEA",
"icon": "refresh"
},
"partial": {
"background": "#FFB80015",
"text": "#FFB800",
"icon": "partial-circle"
}
},
"components": {
"balanceCard": {
"padding": 20,
"radius": 24,
"statBoxWidth": 100,
"statBoxHeight": 60,
"gap": 12
},
"streakBanner": {
"height": 80,
"padding": 16,
"progressHeight": 6,
"progressRadius": 3,
"fireIconSize": 24
},
"quickAction": {
"size": 72,
"iconSize": 28,
"radius": 16,
"gap": 12
},
"filterTab": {
"height": 36,
"padding": 16,
"gap": 8,
"indicatorHeight": 2
},
"chargeCard": {
"minHeight": 120,
"padding": 16,
"radius": 20,
"iconSize": 48,
"gap": 12,
"actionButtonHeight": 36
},
"statusChip": {
"height": 24,
"paddingHorizontal": 8,
"radius": 12,
"fontSize": 11,
"gap": 8
},
"calendarDay": {
"size": 40,
"indicatorSize": 8,
"selectedRadius": 20,
"amountFontSize": 10
},
"planCard": {
"padding": 16,
"radius": 16,
"timelineHeight": 4,
"timelineDotSize": 12,
"variants": {
"default": { "bg": "#FFFFFF", "border": "#E1E4E8" },
"selected": { "bg": "gradient@8%", "border": "gradient" }
}
},
"progressBar": {
"height": 6,
"radius": 3,
"trackColor": "#E1E4E8"
},
"amountBreakdown": {
"rowHeight": 48,
"padding": 16,
"radius": 16
},
"timeline": {
"lineWidth": 2,
"dotSize": 12,
"gap": 24,
"colors": {
"active": "#00D09C",
"confirmed": "#FFB800",
"pending": "#667EEA"
}
},
"aiTipCard": {
"padding": 16,
"radius": 12,
"iconSize": 20,
"background": "#667EEA08"
},
"checkboxCard": {
"padding": 16,
"radius": 12,
"checkboxSize": 24,
"gap": 12
}
},
"animation": {
"streakFlame": {
"duration": 2000,
"type": "flicker",
"intensity": "subtle"
},
"confetti": {
"duration": 2000,
"particles": 20,
"colors": ["#667EEA", "#764BA2", "#00D09C", "#FFB800"]
},
"progressFill": {
"duration": 600,
"easing": "cubic-bezier(0.0, 0.0, 0.2, 1)"
},
"cardPress": {
"scale": 0.98,
"duration": 150
},
"successCheck": {
"duration": 600,
"type": "draw-stroke"
},
"counterIncrement": {
"duration": 300,
"type": "scale-pulse"
},
"timelineConnect": {
"duration": 400,
"stagger": 200
}
},
"screens": [
"smartDashboard",
"calendarView",
"chargeDetail",
"autopaySetupStep1",
"autopaySetupStep2",
"autopaySetupStep3",
"splitPayment",
"paymentSuccess",
"chargeInsights",
"waiverRequest",
"emptyState",
"loadingState"
]
}

View File

@ -1,936 +0,0 @@
# Dashboard - API Reference
> **Base URL**: `https://tt.mifos.community/fineract-provider/api/v1/self/`
> **Authentication**: Basic Auth with `Fineract-Platform-TenantId` header
> **Last Updated**: 2025-12-28
---
## Authentication Headers
All endpoints require:
```
Headers:
Authorization: Basic {base64EncodedAuthenticationKey}
Fineract-Platform-TenantId: {tenantId}
Content-Type: application/json
```
---
## 1. Client Details
### GET /self/clients/{clientId}
**Purpose**: Fetch client information for dashboard greeting and profile
**Request**:
```
GET /self/clients/123
```
**Response**:
```json
{
"id": 123,
"accountNo": "CL-0000123",
"status": {
"id": 300,
"code": "clientStatusType.active",
"value": "Active"
},
"active": true,
"activationDate": [2023, 1, 15],
"firstname": "John",
"middlename": "M",
"lastname": "Doe",
"displayName": "John M. Doe",
"mobileNo": "1234567890",
"emailAddress": "john.doe@example.com",
"dateOfBirth": [1990, 5, 20],
"gender": {
"id": 22,
"name": "Male"
},
"officeId": 1,
"officeName": "Head Office",
"timeline": {
"submittedOnDate": [2023, 1, 10],
"activatedOnDate": [2023, 1, 15]
}
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class Client(
@SerialName("id") val id: Long,
@SerialName("accountNo") val accountNo: String? = null,
@SerialName("status") val status: ClientStatus? = null,
@SerialName("active") val active: Boolean = false,
@SerialName("activationDate") val activationDate: List<Int>? = null,
@SerialName("firstname") val firstname: String? = null,
@SerialName("middlename") val middlename: String? = null,
@SerialName("lastname") val lastname: String? = null,
@SerialName("displayName") val displayName: String? = null,
@SerialName("mobileNo") val mobileNo: String? = null,
@SerialName("emailAddress") val emailAddress: String? = null,
@SerialName("dateOfBirth") val dateOfBirth: List<Int>? = null,
@SerialName("gender") val gender: Gender? = null,
@SerialName("officeId") val officeId: Long? = null,
@SerialName("officeName") val officeName: String? = null,
)
@Serializable
data class ClientStatus(
@SerialName("id") val id: Int,
@SerialName("code") val code: String? = null,
@SerialName("value") val value: String? = null,
)
```
**Status**: Implemented in ClientService
---
## 2. Client Accounts Overview
### GET /self/clients/{clientId}/accounts
**Purpose**: Fetch all account summaries for dashboard net worth calculation
**Request**:
```
GET /self/clients/123/accounts
```
**Response**:
```json
{
"savingsAccounts": [
{
"id": 1001,
"accountNo": "SA-0001234567",
"productId": 1,
"productName": "Savings Plus",
"shortProductName": "SP",
"status": {
"id": 300,
"code": "savingsAccountStatusType.active",
"value": "Active",
"submittedAndPendingApproval": false,
"approved": true,
"rejected": false,
"withdrawnByApplicant": false,
"active": true,
"closed": false
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"accountBalance": 35000.00,
"accountType": {
"id": 100,
"code": "accountType.individual",
"value": "Individual"
},
"depositType": {
"id": 100,
"code": "depositAccountType.savingsDeposit",
"value": "Savings"
}
}
],
"loanAccounts": [
{
"id": 2001,
"accountNo": "LA-0009876543",
"productId": 2,
"productName": "Personal Loan",
"shortProductName": "PL",
"status": {
"id": 300,
"code": "loanStatusType.active",
"value": "Active",
"active": true
},
"loanType": {
"id": 1,
"code": "accountType.individual",
"value": "Individual"
},
"loanCycle": 1,
"principal": 10000.00,
"loanBalance": 6750.00,
"amountPaid": 3250.00,
"inArrears": false
}
],
"shareAccounts": [
{
"id": 3001,
"accountNo": "SH-0005678901",
"productId": 3,
"productName": "Equity Shares",
"status": {
"id": 300,
"code": "shareAccountStatusType.active",
"value": "Active",
"active": true
},
"totalApprovedShares": 100,
"totalPendingForApprovalShares": 0
}
]
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class ClientAccounts(
@SerialName("savingsAccounts") val savingsAccounts: List<SavingAccount>? = null,
@SerialName("loanAccounts") val loanAccounts: List<LoanAccount> = emptyList(),
@SerialName("shareAccounts") val shareAccounts: List<ShareAccount> = emptyList(),
)
@Serializable
data class SavingAccount(
@SerialName("id") val id: Long,
@SerialName("accountNo") val accountNo: String? = null,
@SerialName("productId") val productId: Long? = null,
@SerialName("productName") val productName: String? = null,
@SerialName("status") val status: SavingsStatus? = null,
@SerialName("currency") val currency: Currency? = null,
@SerialName("accountBalance") val accountBalance: Double? = null,
@SerialName("depositType") val depositType: DepositType? = null,
)
@Serializable
data class LoanAccount(
@SerialName("id") val id: Long,
@SerialName("accountNo") val accountNo: String? = null,
@SerialName("productId") val productId: Long? = null,
@SerialName("productName") val productName: String? = null,
@SerialName("status") val status: LoanStatus? = null,
@SerialName("loanType") val loanType: LoanType? = null,
@SerialName("principal") val principal: Double? = null,
@SerialName("loanBalance") val loanBalance: Double? = null,
@SerialName("amountPaid") val amountPaid: Double? = null,
@SerialName("inArrears") val inArrears: Boolean = false,
)
@Serializable
data class ShareAccount(
@SerialName("id") val id: Long,
@SerialName("accountNo") val accountNo: String? = null,
@SerialName("productId") val productId: Long? = null,
@SerialName("productName") val productName: String? = null,
@SerialName("status") val status: ShareStatus? = null,
@SerialName("totalApprovedShares") val totalApprovedShares: Int? = null,
@SerialName("totalPendingForApprovalShares") val totalPendingForApprovalShares: Int? = null,
)
```
**Status**: Implemented in ClientService
---
## 3. Client Profile Image
### GET /self/clients/{clientId}/images
**Purpose**: Fetch client profile image for dashboard avatar
**Request**:
```
GET /self/clients/123/images
Accept: application/octet-stream
```
**Response**:
```
Binary image data (JPEG/PNG)
```
**Alternative Response** (Base64):
```
GET /self/clients/123/images?maxWidth=200&maxHeight=200
Accept: text/plain
Response: Base64 encoded image string
```
**Kotlin Implementation**:
```kotlin
suspend fun getClientImage(clientId: Long): ByteArray? {
return try {
clientService.getClientImage(clientId)
} catch (e: Exception) {
null // Return null if no image exists
}
}
```
**Status**: Implemented in ClientService
---
## 4. Client Transactions
### GET /self/clients/{clientId}/transactions
**Purpose**: Fetch recent transactions across all accounts
**Request**:
```
GET /self/clients/123/transactions?offset=0&limit=20
```
**Query Parameters**:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| offset | Int | 0 | Pagination offset |
| limit | Int | 50 | Number of records |
**Response**:
```json
{
"totalFilteredRecords": 150,
"pageItems": [
{
"id": 10001,
"officeId": 1,
"officeName": "Head Office",
"type": {
"id": 1,
"code": "savingsAccountTransactionType.deposit",
"value": "Deposit",
"deposit": true,
"withdrawal": false,
"interestPosting": false,
"feeDeduction": false
},
"date": [2025, 12, 28],
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"amount": 4500.00,
"submittedOnDate": [2025, 12, 28],
"reversed": false,
"submittedByUsername": "system",
"accountId": 1001,
"accountNo": "SA-0001234567",
"accountType": {
"id": 2,
"code": "accountType.savings",
"value": "Savings Account"
},
"runningBalance": 35000.00,
"transfer": null
}
]
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class TransactionPage(
@SerialName("totalFilteredRecords") val totalFilteredRecords: Int,
@SerialName("pageItems") val pageItems: List<Transaction>,
)
@Serializable
data class Transaction(
@SerialName("id") val id: Long,
@SerialName("officeId") val officeId: Long? = null,
@SerialName("officeName") val officeName: String? = null,
@SerialName("type") val type: TransactionType? = null,
@SerialName("date") val date: List<Int>? = null,
@SerialName("currency") val currency: Currency? = null,
@SerialName("amount") val amount: Double? = null,
@SerialName("reversed") val reversed: Boolean = false,
@SerialName("accountId") val accountId: Long? = null,
@SerialName("accountNo") val accountNo: String? = null,
@SerialName("runningBalance") val runningBalance: Double? = null,
@SerialName("transfer") val transfer: TransferDetail? = null,
)
@Serializable
data class TransactionType(
@SerialName("id") val id: Int,
@SerialName("code") val code: String? = null,
@SerialName("value") val value: String? = null,
@SerialName("deposit") val deposit: Boolean = false,
@SerialName("withdrawal") val withdrawal: Boolean = false,
@SerialName("interestPosting") val interestPosting: Boolean = false,
@SerialName("feeDeduction") val feeDeduction: Boolean = false,
)
```
**Status**: Implemented in RecentTransactionService
---
## 5. Savings Account Details
### GET /self/savingsaccounts/{accountId}
**Purpose**: Fetch detailed savings account information
**Request**:
```
GET /self/savingsaccounts/1001
```
**Query Parameters**:
| Parameter | Type | Description |
|-----------|------|-------------|
| associations | String | Include related data (transactions, charges) |
**Response**:
```json
{
"id": 1001,
"accountNo": "SA-0001234567",
"clientId": 123,
"clientName": "John Doe",
"savingsProductId": 1,
"savingsProductName": "Savings Plus",
"fieldOfficerId": 1,
"fieldOfficerName": "Officer Name",
"status": {
"id": 300,
"code": "savingsAccountStatusType.active",
"value": "Active",
"active": true
},
"timeline": {
"submittedOnDate": [2023, 1, 10],
"approvedOnDate": [2023, 1, 12],
"activatedOnDate": [2023, 1, 15]
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$"
},
"nominalAnnualInterestRate": 4.5,
"interestCompoundingPeriodType": {
"id": 1,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Daily"
},
"interestPostingPeriodType": {
"id": 4,
"code": "savings.interest.period.savingsPostingInterestPeriodType.monthly",
"value": "Monthly"
},
"interestCalculationType": {
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
"interestCalculationDaysInYearType": {
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
},
"minRequiredOpeningBalance": 500.00,
"withdrawalFeeForTransfers": false,
"allowOverdraft": false,
"summary": {
"currency": {
"code": "USD",
"displaySymbol": "$"
},
"totalDeposits": 42500.00,
"totalWithdrawals": 7500.00,
"totalInterestEarned": 1250.00,
"totalInterestPosted": 1250.00,
"accountBalance": 35000.00,
"availableBalance": 34500.00
},
"transactions": [],
"charges": []
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class SavingsAccountDetail(
@SerialName("id") val id: Long,
@SerialName("accountNo") val accountNo: String? = null,
@SerialName("clientId") val clientId: Long? = null,
@SerialName("clientName") val clientName: String? = null,
@SerialName("savingsProductName") val savingsProductName: String? = null,
@SerialName("status") val status: SavingsStatus? = null,
@SerialName("currency") val currency: Currency? = null,
@SerialName("nominalAnnualInterestRate") val nominalAnnualInterestRate: Double? = null,
@SerialName("minRequiredOpeningBalance") val minRequiredOpeningBalance: Double? = null,
@SerialName("summary") val summary: SavingsSummary? = null,
@SerialName("transactions") val transactions: List<SavingsTransaction>? = null,
@SerialName("charges") val charges: List<Charge>? = null,
)
@Serializable
data class SavingsSummary(
@SerialName("totalDeposits") val totalDeposits: Double? = null,
@SerialName("totalWithdrawals") val totalWithdrawals: Double? = null,
@SerialName("totalInterestEarned") val totalInterestEarned: Double? = null,
@SerialName("totalInterestPosted") val totalInterestPosted: Double? = null,
@SerialName("accountBalance") val accountBalance: Double? = null,
@SerialName("availableBalance") val availableBalance: Double? = null,
)
```
**Status**: Implemented in SavingsAccountService
---
## 6. Loan Account Details
### GET /self/loans/{loanId}
**Purpose**: Fetch detailed loan account information
**Request**:
```
GET /self/loans/2001?associations=repaymentSchedule,transactions
```
**Query Parameters**:
| Parameter | Type | Description |
|-----------|------|-------------|
| associations | String | Include: repaymentSchedule, transactions, all |
**Response**:
```json
{
"id": 2001,
"accountNo": "LA-0009876543",
"clientId": 123,
"clientName": "John Doe",
"clientOfficeId": 1,
"loanProductId": 2,
"loanProductName": "Personal Loan",
"loanProductDescription": "Personal unsecured loan",
"loanPurposeName": "Personal Use",
"status": {
"id": 300,
"code": "loanStatusType.active",
"value": "Active",
"active": true
},
"loanType": {
"id": 1,
"code": "accountType.individual",
"value": "Individual"
},
"currency": {
"code": "USD",
"displaySymbol": "$",
"decimalPlaces": 2
},
"principal": 10000.00,
"approvedPrincipal": 10000.00,
"termFrequency": 12,
"termPeriodFrequencyType": {
"id": 2,
"code": "termFrequency.periodFrequencyType.months",
"value": "Months"
},
"numberOfRepayments": 12,
"repaymentEvery": 1,
"repaymentFrequencyType": {
"id": 2,
"value": "Months"
},
"interestRatePerPeriod": 12.0,
"annualInterestRate": 12.0,
"timeline": {
"submittedOnDate": [2024, 1, 1],
"approvedOnDate": [2024, 1, 5],
"disbursedOnDate": [2024, 1, 10],
"expectedMaturityDate": [2025, 1, 10]
},
"summary": {
"currency": {
"code": "USD",
"displaySymbol": "$"
},
"principalDisbursed": 10000.00,
"principalPaid": 3250.00,
"principalOutstanding": 6750.00,
"interestCharged": 600.00,
"interestPaid": 400.00,
"interestOutstanding": 200.00,
"feeChargesCharged": 50.00,
"feeChargesPaid": 50.00,
"feeChargesOutstanding": 0.00,
"totalExpectedRepayment": 10650.00,
"totalRepayment": 3700.00,
"totalOutstanding": 6950.00
},
"repaymentSchedule": {
"currency": {
"code": "USD"
},
"loanTermInDays": 365,
"totalPrincipalDisbursed": 10000.00,
"totalPrincipalExpected": 10000.00,
"totalPrincipalPaid": 3250.00,
"totalInterestCharged": 600.00,
"totalFeeChargesCharged": 50.00,
"totalRepaymentExpected": 10650.00,
"totalRepayment": 3700.00,
"totalOutstanding": 6950.00,
"periods": []
},
"transactions": [],
"inArrears": false
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class LoanAccountDetail(
@SerialName("id") val id: Long,
@SerialName("accountNo") val accountNo: String? = null,
@SerialName("clientId") val clientId: Long? = null,
@SerialName("clientName") val clientName: String? = null,
@SerialName("loanProductName") val loanProductName: String? = null,
@SerialName("status") val status: LoanStatus? = null,
@SerialName("currency") val currency: Currency? = null,
@SerialName("principal") val principal: Double? = null,
@SerialName("approvedPrincipal") val approvedPrincipal: Double? = null,
@SerialName("numberOfRepayments") val numberOfRepayments: Int? = null,
@SerialName("annualInterestRate") val annualInterestRate: Double? = null,
@SerialName("timeline") val timeline: LoanTimeline? = null,
@SerialName("summary") val summary: LoanSummary? = null,
@SerialName("repaymentSchedule") val repaymentSchedule: RepaymentSchedule? = null,
@SerialName("inArrears") val inArrears: Boolean = false,
)
@Serializable
data class LoanSummary(
@SerialName("principalDisbursed") val principalDisbursed: Double? = null,
@SerialName("principalPaid") val principalPaid: Double? = null,
@SerialName("principalOutstanding") val principalOutstanding: Double? = null,
@SerialName("interestCharged") val interestCharged: Double? = null,
@SerialName("interestPaid") val interestPaid: Double? = null,
@SerialName("interestOutstanding") val interestOutstanding: Double? = null,
@SerialName("totalExpectedRepayment") val totalExpectedRepayment: Double? = null,
@SerialName("totalRepayment") val totalRepayment: Double? = null,
@SerialName("totalOutstanding") val totalOutstanding: Double? = null,
)
```
**Status**: Implemented in LoanAccountService
---
## 7. Beneficiary List
### GET /self/beneficiaries/tpt
**Purpose**: Fetch beneficiaries for third-party transfers
**Request**:
```
GET /self/beneficiaries/tpt
```
**Response**:
```json
[
{
"id": 5001,
"name": "Jane Doe",
"officeName": "Head Office",
"clientName": "Jane Doe",
"accountType": {
"id": 2,
"code": "accountType.savings",
"value": "Savings Account"
},
"accountNumber": "SA-0007654321",
"transferLimit": 10000.00
}
]
```
**Kotlin DTO**:
```kotlin
@Serializable
data class Beneficiary(
@SerialName("id") val id: Long,
@SerialName("name") val name: String? = null,
@SerialName("officeName") val officeName: String? = null,
@SerialName("clientName") val clientName: String? = null,
@SerialName("accountType") val accountType: AccountType? = null,
@SerialName("accountNumber") val accountNumber: String? = null,
@SerialName("transferLimit") val transferLimit: Double? = null,
)
```
**Status**: Implemented in BeneficiaryService
---
## 8. Transfer Template
### GET /self/accounttransfers/template
**Purpose**: Get transfer options and account templates
**Request**:
```
GET /self/accounttransfers/template?type=tpt
```
**Query Parameters**:
| Parameter | Type | Description |
|-----------|------|-------------|
| type | String | Transfer type: "tpt" (third-party) |
| fromAccountId | Long | Source account ID |
| fromAccountType | Int | 1=Loan, 2=Savings |
**Response**:
```json
{
"fromAccountOptions": [
{
"accountId": 1001,
"accountNo": "SA-0001234567",
"accountType": {
"id": 2,
"value": "Savings Account"
},
"clientId": 123,
"clientName": "John Doe",
"officeId": 1,
"officeName": "Head Office"
}
],
"toAccountOptions": [
{
"accountId": 1002,
"accountNo": "SA-0009876543",
"accountType": {
"id": 2,
"value": "Savings Account"
},
"clientId": 456,
"clientName": "Jane Doe"
}
],
"transferTypes": [
{
"id": 1,
"code": "accountTransferType.account.transfer",
"value": "Account Transfer"
}
]
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class AccountTransferTemplate(
@SerialName("fromAccountOptions") val fromAccountOptions: List<AccountOption>? = null,
@SerialName("toAccountOptions") val toAccountOptions: List<AccountOption>? = null,
@SerialName("transferTypes") val transferTypes: List<TransferType>? = null,
)
@Serializable
data class AccountOption(
@SerialName("accountId") val accountId: Long,
@SerialName("accountNo") val accountNo: String? = null,
@SerialName("accountType") val accountType: AccountType? = null,
@SerialName("clientId") val clientId: Long? = null,
@SerialName("clientName") val clientName: String? = null,
@SerialName("officeId") val officeId: Long? = null,
@SerialName("officeName") val officeName: String? = null,
)
```
**Status**: Implemented in ThirdPartyTransferService
---
## 9. Execute Transfer
### POST /self/accounttransfers
**Purpose**: Execute a fund transfer between accounts
**Request**:
```json
POST /self/accounttransfers
{
"fromOfficeId": 1,
"fromClientId": 123,
"fromAccountType": 2,
"fromAccountId": 1001,
"toOfficeId": 1,
"toClientId": 456,
"toAccountType": 2,
"toAccountId": 1002,
"dateFormat": "dd MMMM yyyy",
"locale": "en",
"transferDate": "28 December 2025",
"transferAmount": 500.00,
"transferDescription": "Payment for dinner"
}
```
**Response**:
```json
{
"savingsId": 1001,
"resourceId": 50001,
"changes": {
"transferDate": "28 December 2025",
"transferAmount": 500.00,
"transferDescription": "Payment for dinner"
}
}
```
**Kotlin DTO**:
```kotlin
@Serializable
data class TransferPayload(
@SerialName("fromOfficeId") val fromOfficeId: Long,
@SerialName("fromClientId") val fromClientId: Long,
@SerialName("fromAccountType") val fromAccountType: Int,
@SerialName("fromAccountId") val fromAccountId: Long,
@SerialName("toOfficeId") val toOfficeId: Long,
@SerialName("toClientId") val toClientId: Long,
@SerialName("toAccountType") val toAccountType: Int,
@SerialName("toAccountId") val toAccountId: Long,
@SerialName("dateFormat") val dateFormat: String = "dd MMMM yyyy",
@SerialName("locale") val locale: String = "en",
@SerialName("transferDate") val transferDate: String,
@SerialName("transferAmount") val transferAmount: Double,
@SerialName("transferDescription") val transferDescription: String? = null,
)
@Serializable
data class TransferResponse(
@SerialName("savingsId") val savingsId: Long? = null,
@SerialName("resourceId") val resourceId: Long? = null,
@SerialName("changes") val changes: Map<String, Any>? = null,
)
```
**Status**: Implemented in ThirdPartyTransferService
---
## 10. Third-Party Transfer
### POST /self/accounttransfers?type=tpt
**Purpose**: Execute transfer to a saved beneficiary
**Request**:
```json
POST /self/accounttransfers?type=tpt
{
"fromAccountId": 1001,
"fromAccountType": 2,
"toAccountId": 5001,
"dateFormat": "dd MMMM yyyy",
"locale": "en",
"transferDate": "28 December 2025",
"transferAmount": 500.00,
"transferDescription": "Monthly support"
}
```
**Response**: Same as standard transfer
**Status**: Implemented in ThirdPartyTransferService
---
## API Summary Table
| Endpoint | Method | Service | Repository | Priority |
|----------|--------|---------|------------|----------|
| /self/clients/{id} | GET | ClientService | ClientRepository | P0 |
| /self/clients/{id}/accounts | GET | ClientService | ClientRepository | P0 |
| /self/clients/{id}/images | GET | ClientService | ClientRepository | P1 |
| /self/clients/{id}/transactions | GET | RecentTransactionService | RecentTransactionRepository | P0 |
| /self/savingsaccounts/{id} | GET | SavingsAccountService | SavingsAccountRepository | P0 |
| /self/loans/{id} | GET | LoanAccountService | LoanAccountRepository | P0 |
| /self/beneficiaries/tpt | GET | BeneficiaryService | BeneficiaryRepository | P1 |
| /self/accounttransfers/template | GET | ThirdPartyTransferService | TransferRepository | P1 |
| /self/accounttransfers | POST | ThirdPartyTransferService | TransferRepository | P0 |
---
## Error Responses
| Status Code | Error | Description | User Message |
|-------------|-------|-------------|--------------|
| 400 | Bad Request | Invalid request payload | "Please check your input" |
| 401 | Unauthorized | Invalid/expired token | "Please login again" |
| 403 | Forbidden | Insufficient permissions | "Access denied" |
| 404 | Not Found | Resource doesn't exist | "Account not found" |
| 409 | Conflict | Business rule violation | "Insufficient balance" |
| 500 | Server Error | Internal server error | "Service unavailable" |
**Error Response Format**:
```json
{
"developerMessage": "Detailed error for debugging",
"httpStatusCode": "400",
"defaultUserMessage": "User-friendly error message",
"userMessageGlobalisationCode": "error.msg.code",
"errors": [
{
"developerMessage": "Field-specific error",
"defaultUserMessage": "Amount must be greater than 0",
"userMessageGlobalisationCode": "validation.msg.amount.invalid",
"parameterName": "transferAmount"
}
]
}
```
---
## Rate Limiting
| Operation | Limit | Window |
|-----------|-------|--------|
| Read operations | 100 | Per minute |
| Write operations | 20 | Per minute |
| Transfers | 10 | Per hour |
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-28 | Initial production-level API documentation |

View File

@ -1,485 +0,0 @@
# Dashboard - Feature Specification
> **Purpose**: Unified account management dashboard for end users
> **User Value**: Single view of all financial accounts with quick actions
> **Last Updated**: 2025-12-28
> **Status**: Production Design
---
## 1. Overview
### 1.1 Feature Summary
The Dashboard provides a comprehensive, unified view of the user's complete financial portfolio. It aggregates savings, loans, and share accounts into an intuitive interface with real-time balances, quick actions, and seamless navigation to detailed account management.
### 1.2 User Stories
- As a user, I want to see my total net worth at a glance
- As a user, I want to quickly identify which accounts need attention
- As a user, I want to transfer money with minimal steps
- As a user, I want to track my loan repayment progress
- As a user, I want to see recent transactions across all accounts
- As a user, I want to manage beneficiaries for quick transfers
### 1.3 Design Principles
- **Clarity**: Information hierarchy prioritizes most important data
- **Speed**: One-tap access to frequent actions
- **Trust**: Clear display of financial figures with currency formatting
- **Accessibility**: WCAG 2.1 AA compliant design
---
## 2. Screen Layout
### 2.1 Main Dashboard
```
┌─────────────────────────────────────────────────────────────┐
│ ← Dashboard 🔔 ⚙️ │
├─────────────────────────────────────────────────────────────┤
│ │
│ Good morning, John │
│ December 28, 2025 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ TOTAL NET WORTH 👁 │ │
│ │ ┌───────────────────────────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ $ 45,750.00 │ │ │
│ │ │ │ │ │
│ │ │ ↑ +$1,250.00 this month │ │ │
│ │ └───────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Savings Loans Shares │ │
│ │ $52,500 -$6,750 $0 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ QUICK ACTIONS │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │ 💸 │ │ 📥 │ │ 📊 │ │ 👥 │ │ │
│ │ │Transfer│ │Deposit │ │ Invest │ │ Benef. │ │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ MY ACCOUNTS View All → │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 💰 Primary Savings $ 35,000.00 │ │
│ │ SA-0001234567 • Active │ │
│ │ Interest Rate: 4.5% p.a. │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 💰 Emergency Fund $ 17,500.00 │ │
│ │ SA-0001234568 • Active │ │
│ │ Interest Rate: 3.2% p.a. │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 🏦 Personal Loan -$ 6,750.00 │ │
│ │ LA-0009876543 • Active │ │
│ │ ████████░░ 80% paid • Due: Jan 15 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ RECENT ACTIVITY View All → │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Today │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ ↓ Salary Credit + $4,500.00 │ │ │
│ │ │ Primary Savings • 09:30 AM │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ ↑ Bill Payment - $150.00 │ │ │
│ │ │ Primary Savings • 08:15 AM │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Yesterday │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ ↓ Interest Credit + $125.50 │ │ │
│ │ │ Emergency Fund • 11:59 PM │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ [Powered by Mifos] │
└─────────────────────────────────────────────────────────────┘
```
### 2.2 Account Detail View
```
┌─────────────────────────────────────────────────────────────┐
│ ← Primary Savings ⋮ │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ $ 35,000.00 │ │
│ │ Available Balance │ │
│ │ │ │
│ │ Account: SA-0001234567 │ │
│ │ Status: Active • Since: Jan 2023 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Transfer│ │ Withdraw│ │Statement│ │ QR Pay │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ ACCOUNT DETAILS │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Product Name Savings Plus │ │
│ │ Interest Rate 4.5% per annum │ │
│ │ Total Deposits $ 42,500.00 │ │
│ │ Total Withdrawals $ 7,500.00 │ │
│ │ Total Interest $ 1,250.00 │ │
│ │ Minimum Balance $ 500.00 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ TRANSACTIONS Filter ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Dec 28 Salary Credit + $4,500.00 │ │
│ │ Dec 27 Transfer to John - $500.00 │ │
│ │ Dec 26 Interest Posting + $45.50 │ │
│ │ Dec 25 ATM Withdrawal - $200.00 │ │
│ │ Dec 24 Online Purchase - $89.99 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ CHARGES │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Monthly Maintenance Due: Jan 1 $ 5.00 │ │
│ │ Annual Fee Paid: Dec 1 $ 25.00 ✓ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
```
### 2.3 Transfer Flow
```
┌─────────────────────────────────────────────────────────────┐
│ ← Transfer Money │
├─────────────────────────────────────────────────────────────┤
│ │
│ FROM ACCOUNT │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 💰 Primary Savings ▼ │ │
│ │ Available: $35,000.00 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ TO │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ○ My Account ○ Beneficiary ○ New Recipient │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ SELECT BENEFICIARY │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 👤 Jane Doe │ │
│ │ ****4567 • Mifos Bank │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 👤 Mike Smith │ │
│ │ ****8901 • Mifos Bank │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ AMOUNT │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ $ │ │
│ │ 500.00 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ REMARKS (Optional) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Payment for dinner │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ CONTINUE TO REVIEW │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## 3. Components Breakdown
### 3.1 Net Worth Card
| Property | Type | Description |
|----------|------|-------------|
| totalNetWorth | Double | Sum of all accounts (savings - loans + shares) |
| monthlyChange | Double | Change from previous month |
| savingsTotal | Double | Sum of all savings account balances |
| loansTotal | Double | Sum of all loan outstanding balances |
| sharesTotal | Double | Sum of all share account values |
| isAmountVisible | Boolean | Toggle for privacy mode |
| currency | Currency | User's primary currency |
### 3.2 Account Card
| Property | Type | Description |
|----------|------|-------------|
| accountId | Long | Unique account identifier |
| accountNo | String | Display account number |
| productName | String | Account product type |
| balance | Double | Current balance |
| status | AccountStatus | ACTIVE, PENDING, CLOSED |
| accountType | AccountType | SAVINGS, LOAN, SHARE |
| interestRate | Double | Annual interest rate |
| progressPercent | Int? | Loan repayment progress (loans only) |
| nextDueDate | Date? | Next payment due (loans only) |
### 3.3 Transaction Item
| Property | Type | Description |
|----------|------|-------------|
| transactionId | Long | Unique transaction ID |
| transactionType | TransactionType | CREDIT, DEBIT |
| amount | Double | Transaction amount |
| description | String | Transaction description |
| accountName | String | Associated account |
| timestamp | DateTime | Transaction date/time |
| runningBalance | Double | Balance after transaction |
### 3.4 Quick Action
| Action | Icon | Route | Permission |
|--------|------|-------|------------|
| Transfer | 💸 | /transfer | Always |
| Deposit | 📥 | /deposit | If savings exists |
| Invest | 📊 | /share-apply | Always |
| Beneficiary | 👥 | /beneficiary | Always |
| Pay Loan | 🏦 | /loan-payment | If loan exists |
| Statement | 📄 | /statement | Always |
---
## 4. State Model
```kotlin
@Immutable
data class DashboardState(
// User Info
val clientId: Long = 0,
val firstName: String = "",
val greeting: String = "",
val profileImage: ByteArray? = null,
// Aggregated Balances
val totalNetWorth: Double = 0.0,
val monthlyChange: Double = 0.0,
val savingsTotal: Double = 0.0,
val loansTotal: Double = 0.0,
val sharesTotal: Double = 0.0,
val currency: String = "USD",
val currencySymbol: String = "$",
val decimalPlaces: Int = 2,
// Account Lists
val savingsAccounts: List<SavingAccount> = emptyList(),
val loanAccounts: List<LoanAccount> = emptyList(),
val shareAccounts: List<ShareAccount> = emptyList(),
// Recent Activity
val recentTransactions: List<Transaction> = emptyList(),
// UI State
val isAmountVisible: Boolean = true,
val isRefreshing: Boolean = false,
val notificationCount: Int = 0,
val networkStatus: Boolean = true,
val uiState: DashboardUiState = DashboardUiState.Loading,
val dialogState: DialogState? = null,
)
sealed interface DashboardUiState {
data object Loading : DashboardUiState
data object Success : DashboardUiState
data class Error(val message: StringResource) : DashboardUiState
data object NetworkError : DashboardUiState
data object Empty : DashboardUiState
}
sealed interface DashboardAction {
// Navigation
data class OnAccountClick(val accountId: Long, val type: AccountType) : DashboardAction
data class OnTransactionClick(val transactionId: Long) : DashboardAction
data object OnViewAllAccounts : DashboardAction
data object OnViewAllTransactions : DashboardAction
data object OnNotificationClick : DashboardAction
data object OnSettingsClick : DashboardAction
// Quick Actions
data object OnTransferClick : DashboardAction
data object OnDepositClick : DashboardAction
data object OnInvestClick : DashboardAction
data object OnBeneficiaryClick : DashboardAction
// Data Actions
data object OnRefresh : DashboardAction
data object OnRetry : DashboardAction
data object ToggleAmountVisibility : DashboardAction
data object DismissDialog : DashboardAction
// Internal
sealed interface Internal : DashboardAction {
data class ReceiveClientData(val data: DataState<Client>) : Internal
data class ReceiveAccountsData(val data: DataState<ClientAccounts>) : Internal
data class ReceiveTransactionsData(val data: DataState<List<Transaction>>) : Internal
data class ReceiveNetworkStatus(val isOnline: Boolean) : Internal
}
}
sealed interface DashboardEvent {
data class NavigateToAccount(val accountId: Long, val type: AccountType) : DashboardEvent
data class NavigateToTransaction(val transactionId: Long) : DashboardEvent
data object NavigateToAccounts : DashboardEvent
data object NavigateToTransactions : DashboardEvent
data object NavigateToNotifications : DashboardEvent
data object NavigateToSettings : DashboardEvent
data object NavigateToTransfer : DashboardEvent
data object NavigateToDeposit : DashboardEvent
data object NavigateToInvest : DashboardEvent
data object NavigateToBeneficiary : DashboardEvent
data class ShowToast(val message: StringResource) : DashboardEvent
}
```
---
## 5. API Requirements
| Endpoint | Method | Purpose | Priority |
|----------|--------|---------|----------|
| /self/clients/{id} | GET | Client details & greeting | P0 |
| /self/clients/{id}/accounts | GET | All account summaries | P0 |
| /self/clients/{id}/images | GET | Profile image | P1 |
| /self/clients/{id}/transactions | GET | Recent transactions | P0 |
| /self/savingsaccounts/{id} | GET | Savings details | P0 |
| /self/loans/{id} | GET | Loan details | P0 |
| /self/beneficiaries/tpt | GET | Beneficiary list | P1 |
| /self/accounttransfers/template | GET | Transfer options | P1 |
| /self/accounttransfers | POST | Execute transfer | P0 |
---
## 6. Data Aggregation Logic
### 6.1 Net Worth Calculation
```kotlin
fun calculateNetWorth(accounts: ClientAccounts): Double {
val savingsTotal = accounts.savingsAccounts
?.filter { it.status?.active == true }
?.sumOf { it.accountBalance ?: 0.0 } ?: 0.0
val loansTotal = accounts.loanAccounts
.filter { it.status?.active == true }
.sumOf { it.loanBalance ?: 0.0 }
val sharesTotal = accounts.shareAccounts
.filter { it.status?.active == true }
.sumOf { (it.totalApprovedShares ?: 0) * (it.unitPrice ?: 0.0) }
return savingsTotal - loansTotal + sharesTotal
}
```
### 6.2 Monthly Change Calculation
```kotlin
fun calculateMonthlyChange(
currentTransactions: List<Transaction>,
startOfMonth: Date
): Double {
return currentTransactions
.filter { it.date >= startOfMonth }
.sumOf {
if (it.transactionType?.deposit == true) it.amount ?: 0.0
else -(it.amount ?: 0.0)
}
}
```
### 6.3 Loan Progress Calculation
```kotlin
fun calculateLoanProgress(loan: LoanAccount): Int {
val principal = loan.principal ?: return 0
val outstanding = loan.loanBalance ?: return 100
val paid = principal - outstanding
return ((paid / principal) * 100).toInt().coerceIn(0, 100)
}
```
---
## 7. Greeting Logic
```kotlin
fun getGreeting(hour: Int, firstName: String): String {
val timeGreeting = when (hour) {
in 0..11 -> "Good morning"
in 12..16 -> "Good afternoon"
in 17..20 -> "Good evening"
else -> "Good night"
}
return "$timeGreeting, $firstName"
}
```
---
## 8. Error Handling
| Scenario | UI Behavior | Recovery |
|----------|-------------|----------|
| No internet | Show cached data + banner | Auto-retry on reconnect |
| API timeout | Show error state | Pull-to-refresh |
| Auth expired | Navigate to login | Re-authenticate |
| No accounts | Show empty state + CTA | "Apply for Account" button |
| Partial load | Show available data | Silent background retry |
---
## 9. Performance Requirements
| Metric | Target | Implementation |
|--------|--------|----------------|
| First paint | < 500ms | Skeleton loading |
| Data load | < 2s | Parallel API calls |
| Interaction | < 100ms | Optimistic UI |
| Scroll | 60fps | LazyColumn with keys |
| Memory | < 50MB | Image compression |
---
## 10. Accessibility
| Feature | Implementation |
|---------|----------------|
| Screen Reader | contentDescription on all elements |
| Font Scaling | Supports 200% scaling |
| Color Contrast | WCAG AA (4.5:1 minimum) |
| Touch Targets | 48dp minimum |
| Focus Navigation | Logical tab order |
| Motion | Respects reduced motion setting |
---
## 11. Security Considerations
| Feature | Implementation |
|---------|----------------|
| Amount Masking | Toggle to hide sensitive data |
| Session Timeout | Auto-logout after 5 min inactive |
| Biometric | Required for transfers > $1000 |
| Screenshot | Blocked on sensitive screens |
| Clipboard | Auto-clear after 60 seconds |
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-28 | Initial production-level specification |

View File

@ -1,140 +0,0 @@
# Dashboard Feature - Implementation Status
> **Feature**: Unified Account Management Dashboard
> **Phase**: Design Complete
> **Last Updated**: 2025-12-28
---
## Implementation Checklist
```
Feature: Dashboard
- [x] SPEC.md created
- [x] API.md created
- [ ] Network: Services verified
- [ ] Data: Repository patterns
- [ ] Feature: DashboardViewModel
- [ ] Feature: DashboardScreen
- [ ] Navigation: Route registered
- [ ] DI: Module registered
- [ ] STATUS.md updated (ongoing)
```
---
## Current Status
| Component | Status | Notes |
|-----------|--------|-------|
| SPEC.md | Done | Production-level specification |
| API.md | Done | All /self endpoints documented |
| Client Layer | Exists | Reuse existing services |
| Feature Layer | Planned | New unified dashboard module |
---
## API Implementation Status
| Endpoint | Service | Status |
|----------|---------|--------|
| /self/clients/{id} | ClientService | Implemented |
| /self/clients/{id}/accounts | ClientService | Implemented |
| /self/clients/{id}/images | ClientService | Implemented |
| /self/clients/{id}/transactions | RecentTransactionService | Implemented |
| /self/savingsaccounts/{id} | SavingsAccountService | Implemented |
| /self/loans/{id} | LoanAccountService | Implemented |
| /self/beneficiaries/tpt | BeneficiaryService | Implemented |
| /self/accounttransfers/template | ThirdPartyTransferService | Implemented |
| /self/accounttransfers | ThirdPartyTransferService | Implemented |
---
## Feature Layer Requirements
### New Components Needed
| Component | Type | Description |
|-----------|------|-------------|
| DashboardViewModel | ViewModel | Aggregates data from multiple sources |
| DashboardScreen | Screen | Main unified dashboard UI |
| NetWorthCard | Component | Balance aggregation display |
| AccountCard | Component | Individual account display |
| TransactionItem | Component | Recent activity item |
| QuickActionBar | Component | Quick action buttons |
| DashboardModule | DI | Koin module for dashboard |
### Existing Components to Reuse
| Component | Location | Purpose |
|-----------|----------|---------|
| MifosMobileTheme | core:designsystem | App theme |
| MifosScaffold | core:designsystem | Screen scaffold |
| MifosLoadingWheel | core:ui | Loading state |
| MifosErrorComponent | core:ui | Error display |
| EmptyContentScreen | core:ui | Empty state |
---
## Implementation Priority
| Priority | Task | Estimated Complexity |
|----------|------|---------------------|
| P0 | DashboardViewModel with data aggregation | Medium |
| P0 | DashboardScreen main layout | Medium |
| P0 | NetWorthCard component | Low |
| P0 | AccountCard component | Low |
| P1 | TransactionItem component | Low |
| P1 | QuickActionBar component | Low |
| P2 | Pull-to-refresh functionality | Low |
| P2 | Privacy mode toggle | Low |
---
## Dependencies
### Required Modules
- `core:data` - Repository layer
- `core:network` - API services
- `core:model` - Domain models
- `core:ui` - Shared UI components
- `core:designsystem` - Theme and design tokens
### Related Features
- `feature:home` - Current home implementation (reference)
- `feature:accounts` - Account listing
- `feature:recent-transaction` - Transaction display
- `feature:transfer-process` - Transfer flow
---
## Notes
### Design Decisions
1. **Single Source of Truth**: Dashboard aggregates from existing repositories, no new APIs needed
2. **Reactive Updates**: Uses StateFlow for real-time balance updates
3. **Performance**: Parallel API calls for faster loading
4. **Accessibility**: WCAG 2.1 AA compliant design
### Open Questions
1. Should dashboard replace or complement existing home screen?
2. Offline caching strategy for account balances
3. Real-time notification count integration
---
## Next Steps
1. Run `/implement dashboard` to begin implementation
2. Create DashboardViewModel with data aggregation logic
3. Build DashboardScreen with all components
4. Register navigation route and DI module
5. Update STATUS.md with implementation progress
---
## Changelog
| Date | Change |
|------|--------|
| 2025-12-28 | Created STATUS.md with implementation plan |

View File

@ -1,461 +0,0 @@
# Dashboard - AI Mockup Prompts
> **Generated from**: features/dashboard/SPEC.md
> **Generated on**: 2025-12-28
> **Feature**: Unified Account Management Dashboard
---
## Quick Reference
| AI Tool | Best For | Export to Figma |
|---------|----------|-----------------|
| Google Stitch | Material Design, detailed prompts | Yes (native) |
| Uizard | Quick iterations, sketches | No |
| Visily | Component-focused, lo-fi to hi-fi | Yes |
---
## Screen 1: Main Dashboard
### Google Stitch Prompt (Recommended)
```
Create a mobile banking dashboard screen with Material Design 3:
**App Context:**
Mifos Mobile - Self-service banking app for viewing accounts, transactions, and making transfers.
**Screen Size:** 393 x 852 pixels (iPhone 14 Pro equivalent)
**Header Section:**
- Status bar at top (time, battery, signal icons)
- Greeting text "Good morning, John" in Headline Small (24px)
- Date "December 28, 2025" in Body Medium (14px), gray color
- Two icon buttons on right: notification bell and settings gear
**Hero Card - Net Worth:**
- Full-width card with purple gradient background (#6750A4)
- "TOTAL NET WORTH" label in white, Label Medium (12px)
- Eye icon for privacy toggle on right of label
- Large amount "$ 45,750.00" in Display Medium (45px), white
- Monthly change "+$1,250.00 this month" with up arrow, white 80% opacity
- Three-column breakdown below:
- Savings: $52,500
- Loans: -$6,750
- Shares: $0
- Card has 28px corner radius
**Quick Actions Row:**
- "QUICK ACTIONS" section label
- 4 circular buttons in a row, evenly spaced:
1. Transfer (money send icon)
2. Deposit (download icon)
3. Invest (chart icon)
4. Beneficiary (people icon)
- Each has 48px icon container with primary container color (#EADDFF)
- Label below each icon in Label Medium
**My Accounts Section:**
- "MY ACCOUNTS" header with "View All →" link on right
- Three account cards stacked vertically:
Card 1 - Savings:
- 40px circular icon (wallet) with purple background
- "Primary Savings" title, "SA-0001234567 • Active" subtitle
- "$ 35,000.00" balance on right
- "Interest Rate: 4.5% p.a." in small text
- White background, 12px corner radius, subtle shadow
Card 2 - Emergency Fund:
- Same layout as Card 1
- Balance: "$ 17,500.00"
- "Interest Rate: 3.2% p.a."
Card 3 - Loan:
- Bank icon instead of wallet
- "Personal Loan" title
- Balance: "-$ 6,750.00" (red text)
- Progress bar showing 80% paid (purple fill on gray track)
- "Due: Jan 15" text
**Recent Activity Section:**
- "RECENT ACTIVITY" header with "View All →" link
- "Today" date label in gray
- Two transaction items:
Transaction 1:
- Green circle with down arrow (credit)
- "Salary Credit" description
- "Primary Savings • 09:30 AM" in gray
- "+ $4,500.00" in green on right
Transaction 2:
- Red circle with up arrow (debit)
- "Bill Payment" description
- "Primary Savings • 08:15 AM" in gray
- "- $150.00" in red on right
**Bottom Navigation:**
- 80px height, surface container background
- 5 tabs with icons and labels:
1. Home (house icon) - SELECTED with indicator pill
2. Accounts (card icon)
3. Transfer (send icon)
4. Activity (chart icon)
5. Profile (person icon)
- Selected tab has secondary container color pill behind icon
**Style Guidelines:**
- Font: Inter (all weights)
- Primary color: #6750A4
- Surface: #FFFBFE
- On Surface: #1C1B1F
- On Surface Variant: #49454F
- Error/Debit: #B3261E
- Success/Credit: #2E7D32
- Standard padding: 16px horizontal
- Component gap: 8-16px
- Card shadow: subtle (level 1)
```
### Uizard Prompt
```
Mobile banking dashboard app:
Header:
- "Good morning, John" greeting
- Notification and settings icons
Main card (purple):
- "$45,750.00" large balance
- Eye icon to hide amount
- Savings/Loans/Shares breakdown
4 quick action buttons:
- Transfer, Deposit, Invest, Beneficiary
Account list:
- Primary Savings: $35,000
- Emergency Fund: $17,500
- Personal Loan: -$6,750 with progress bar
Recent transactions:
- Salary +$4,500 (green)
- Bill Payment -$150 (red)
Bottom navigation:
- Home, Accounts, Transfer, Activity, Profile
Style: Material Design 3, purple accent (#6750A4), clean white background
```
### Visily Prompt
```
Design a financial dashboard mobile screen:
Components needed:
□ Status bar: Time, battery, signal
□ Header: Greeting "Good morning, John", date, notification bell, settings gear
□ Hero card (purple #6750A4):
- "TOTAL NET WORTH" label with eye toggle
- Large balance "$45,750.00"
- Monthly change indicator
- 3-column breakdown: Savings | Loans | Shares
□ Quick actions row: 4 circular icon buttons with labels
□ Section header: "MY ACCOUNTS" with "View All" link
□ Account card x3: Icon, name, number, status, balance
□ Section header: "RECENT ACTIVITY" with "View All" link
□ Transaction items: Icon, description, account, time, amount (colored)
□ Bottom navigation: 5 tabs with icons and labels, selected state
Material Design 3 styling
393x852 pixels
Inter font family
```
---
## Screen 2: Account Detail
### Google Stitch Prompt
```
Create a savings account detail screen with Material Design 3:
**Screen Size:** 393 x 852 pixels
**Top Bar:**
- Back arrow on left
- "Primary Savings" as title in Title Large (22px)
- Overflow menu (3 dots) on right
- 64px height, surface color background
**Balance Hero:**
- Large centered amount "$ 35,000.00" in Display Small (36px)
- "Available Balance" label below in Body Medium
- Account number "SA-0001234567" in gray
- "Status: Active • Since: Jan 2023"
- White background, subtle bottom border
**Action Buttons Row:**
- 4 equal-width buttons:
1. Transfer (outlined)
2. Withdraw (outlined)
3. Statement (outlined)
4. QR Pay (outlined)
- Each has icon above label
- 8px gap between buttons
- 16px horizontal padding
**Account Details Card:**
- "ACCOUNT DETAILS" header
- Key-value pairs in two columns:
- Product Name: Savings Plus
- Interest Rate: 4.5% per annum
- Total Deposits: $42,500.00
- Total Withdrawals: $7,500.00
- Total Interest: $1,250.00
- Minimum Balance: $500.00
- Elevated card with 12px radius
**Transactions Section:**
- "TRANSACTIONS" header with Filter dropdown on right
- List of transactions:
- Dec 28: Salary Credit +$4,500.00
- Dec 27: Transfer to John -$500.00
- Dec 26: Interest Posting +$45.50
- Dec 25: ATM Withdrawal -$200.00
- Dec 24: Online Purchase -$89.99
- Each row: Date, Description, Amount (colored)
- Dividers between items
**Charges Section:**
- "CHARGES" header
- Two charge items:
- Monthly Maintenance | Due: Jan 1 | $5.00
- Annual Fee | Paid: Dec 1 | $25.00 ✓
- Gray background for paid items
**Style:** Material Design 3, same colors as dashboard
```
---
## Screen 3: Transfer Flow
### Google Stitch Prompt
```
Create a money transfer screen with Material Design 3:
**Screen Size:** 393 x 852 pixels
**Top Bar:**
- Back arrow on left
- "Transfer Money" title
- No right actions
- Surface color background
**From Account Selector:**
- "FROM ACCOUNT" label in Label Medium, gray
- Dropdown/selector showing:
- Wallet icon
- "Primary Savings" account name
- "Available: $35,000.00" in green
- Chevron down icon on right
- Outlined container with 4px radius
**Transfer Type Toggle:**
- "TO" label
- Three radio options in a row:
- ○ My Account
- ● Beneficiary (selected)
- ○ New Recipient
- Selected option has primary color
**Beneficiary List:**
- "SELECT BENEFICIARY" label
- Two beneficiary cards:
Card 1:
- Avatar with "JD" initials
- "Jane Doe" name
- "****4567 • Mifos Bank" masked account
- Radio selected indicator
Card 2:
- Avatar with "MS" initials
- "Mike Smith" name
- "****8901 • Mifos Bank" masked account
- Radio unselected
**Amount Input:**
- "AMOUNT" label
- Large text field with currency prefix "$"
- "500.00" entered value in Display Small
- Outlined style with primary color border (focused)
**Remarks Input:**
- "REMARKS (Optional)" label
- Text field with "Payment for dinner" entered
- Outlined style, unfocused
**Continue Button:**
- Full-width filled button
- "CONTINUE TO REVIEW" label
- Primary color (#6750A4)
- 48px height, full corner radius
- 16px from bottom
**Style:** Material Design 3, form-focused layout
```
---
## Component Prompts
### Net Worth Card (Standalone)
```
Create a financial summary card component:
- Width: 361px (full width minus 32px padding)
- Height: Auto (approximately 180px)
- Background: Linear gradient from #6750A4 to #7E67B0
- Corner radius: 28px
- Padding: 20px horizontal, 20px vertical
Content:
- Top row: "TOTAL NET WORTH" (Label Medium, white) + eye icon
- Main amount: "$45,750.00" (Display Medium, white, centered)
- Change indicator: "↑ +$1,250.00 this month" (Body Medium, white 80%)
- Divider line (white 20%)
- Bottom row with 3 equal columns:
- Savings: $52,500 (white)
- Loans: -$6,750 (white)
- Shares: $0 (white)
Shadow: Level 2 elevation
```
### Account Card (Standalone)
```
Create a bank account card component:
- Width: 361px
- Height: Auto (approximately 88px)
- Background: White (#FFFBFE)
- Corner radius: 12px
- Shadow: Level 1 elevation
- Padding: 16px
Layout (horizontal):
- Left: 40px circular icon container (#EADDFF background)
- Center (flex):
- Account name in Title Medium (#1C1B1F)
- Account number + status in Body Small (#49454F)
- Optional: Interest rate or due date
- Right: Balance in Title Medium
For loan variant:
- Add 8px tall progress bar below content
- Track: #E7E0EC, Fill: #6750A4
- "XX% paid" label below
```
### Transaction Item (Standalone)
```
Create a transaction list item component:
- Width: 361px
- Height: 72px
- Background: Transparent
- Padding: 8px vertical, 0 horizontal
Layout (horizontal):
- Left: 40px circular indicator
- Credit: Green (#C8E6C9) background, down arrow (#2E7D32)
- Debit: Red (#F9DEDC) background, up arrow (#B3261E)
- Center (flex):
- Description in Body Large (#1C1B1F)
- Account + time in Body Small (#49454F)
- Right: Amount in Title Medium
- Credit: Green (#2E7D32) with + prefix
- Debit: Red (#B3261E) with - prefix
```
---
## Export Instructions
### Google Stitch → Figma
1. Go to [stitch.withgoogle.com](https://stitch.withgoogle.com/)
2. Sign in with Google account
3. Paste the prompt above
4. Click "Generate"
5. Review and iterate if needed
6. Click "Export to Figma"
7. Open in Figma and refine
### After Figma Export
1. **Authenticate Figma MCP** (already connected):
```
# MCP will prompt for authentication on first use
```
2. **Get Figma file URL** after export
3. **Run implementation**:
```
/implement dashboard
```
Claude will read the Figma design via MCP and generate matching Compose code.
---
## Design Token Reference
```json
{
"colors": {
"primary": "#6750A4",
"onPrimary": "#FFFFFF",
"primaryContainer": "#EADDFF",
"surface": "#FFFBFE",
"onSurface": "#1C1B1F",
"onSurfaceVariant": "#49454F",
"error": "#B3261E",
"success": "#2E7D32"
},
"typography": {
"displayMedium": "45px / 400",
"displaySmall": "36px / 400",
"headlineSmall": "24px / 400",
"titleLarge": "22px / 400",
"titleMedium": "16px / 500",
"bodyLarge": "16px / 400",
"bodyMedium": "14px / 400",
"bodySmall": "12px / 400",
"labelMedium": "12px / 500"
},
"spacing": {
"screenPadding": "16px",
"sectionGap": "24px",
"componentGap": "8px",
"cardPadding": "16px"
},
"radius": {
"card": "12px",
"heroCard": "28px",
"button": "24px",
"input": "4px"
}
}
```

View File

@ -1,309 +0,0 @@
# Dashboard - Figma First Draft Prompts
> **Tool**: Figma First Draft (Shift+I in Figma)
> **Style**: Modern Banking, Material Design 3
> **Format**: Natural language prompts optimized for Figma AI
---
## How to Use
1. Open Figma → Create new design file
2. Press `Shift + I` or click "Actions" → "First Draft"
3. Copy each prompt below
4. Generate → Iterate → Refine
---
## Screen 1: Main Dashboard
```
Design a modern mobile banking dashboard for "Mifos Mobile" app.
At the top, show a personalized greeting "Good morning, John" with today's date below it. Add notification and settings icons on the right side.
Create a large purple gradient hero card showing the user's total net worth of $45,750.00 in big white text. Include an eye icon to hide/show the balance. Below the amount, show "+$1,250.00 this month" as a positive indicator. At the bottom of the card, display a breakdown: Savings $52,500, Loans -$6,750, Shares $0.
Add a Quick Actions section with 4 circular buttons in a row: Transfer (send money icon), Deposit (download icon), Invest (chart icon), and Beneficiary (people icon). Each should have a light purple background circle with the icon inside.
Create a "My Accounts" section with a "View All" link. Show 3 account cards stacked:
1. Primary Savings - $35,000.00, active, 4.5% interest rate
2. Emergency Fund - $17,500.00, 3.2% interest rate
3. Personal Loan - negative $6,750.00 in red, with a progress bar showing 80% paid, due Jan 15
Add a "Recent Activity" section showing today's transactions:
- Salary Credit: +$4,500.00 in green with a down arrow icon
- Bill Payment: -$150.00 in red with an up arrow icon
At the bottom, add a navigation bar with 5 tabs: Home (selected with indicator), Accounts, Transfer, Activity, Profile.
Style it like Revolut or Monzo - clean, modern, with purple as the primary accent color.
```
---
## Screen 2: Account Detail
```
Design a savings account detail screen for a banking app.
Show a back arrow and "Primary Savings" as the title in the top bar, with a three-dot menu on the right.
Display the available balance prominently: $35,000.00 in large centered text. Below it show "Available Balance", the account number "SA-0001234567", and status "Active since Jan 2023".
Create 4 action buttons in a row: Transfer, Withdraw, Statement, and QR Pay. Each should be an outlined button with an icon above the label.
Add an Account Details card showing key information in a two-column layout:
- Product Name: Savings Plus
- Interest Rate: 4.5% per annum
- Total Deposits: $42,500.00
- Total Withdrawals: $7,500.00
- Total Interest Earned: $1,250.00
- Minimum Balance: $500.00
Show a Transactions section with a filter dropdown. List recent transactions:
- Dec 28: Salary Credit +$4,500.00 (green)
- Dec 27: Transfer to John -$500.00 (red)
- Dec 26: Interest Posting +$45.50 (green)
- Dec 25: ATM Withdrawal -$200.00 (red)
Add a Charges section showing:
- Monthly Maintenance, Due Jan 1, $5.00
- Annual Fee, Paid Dec 1, $25.00 with a checkmark
```
---
## Screen 3: Transfer Money
```
Design a money transfer screen for a banking app.
Show a back arrow and "Transfer Money" as the title.
Create a "From Account" selector that looks like a dropdown. Display a wallet icon, "Primary Savings" as the account name, and "Available: $35,000.00" in green. Add a chevron icon indicating it can be tapped to change.
Add transfer type options as a row of 3 radio buttons: "My Account", "Beneficiary" (selected), and "New Recipient".
Show a beneficiary selection section with 2 cards:
1. Jane Doe - with avatar showing "JD" initials, masked account "****4567 • Mifos Bank", selected state
2. Mike Smith - with avatar showing "MS" initials, masked account "****8901 • Mifos Bank", unselected
Create a large amount input field with a dollar sign prefix, showing "500.00" entered. Make it prominent and easy to read.
Add a remarks field labeled "Remarks (Optional)" with "Payment for dinner" as example text.
At the bottom, add a prominent "Continue to Review" button in purple that spans the full width.
```
---
## Screen 4: Transfer Confirmation
```
Design a transfer confirmation screen for a banking app.
Show a back arrow and "Confirm Transfer" title.
Create a summary card in the center showing the transfer amount "$500.00" prominently with a downward arrow icon below it.
Display the From section:
- Wallet icon with "Primary Savings"
- Account number below
Display the To section:
- Avatar with initials "JD"
- "Jane Doe" name
- Masked account number
Show transfer details:
- Transfer Type: Beneficiary Transfer
- Remarks: Payment for dinner
- Fee: $0.00
- Total: $500.00
Add a large "Confirm Transfer" button in purple at the bottom.
Below the button, add a "Cancel" text link in gray.
```
---
## Screen 5: Transfer Success
```
Design a success celebration screen shown after completing a money transfer.
In the center, show a large green checkmark icon with a circular background. Add subtle confetti or celebration particles around it to make it feel rewarding.
Display "Transfer Successful!" as a bold heading.
Show the amount "$500.00" prominently below.
Add details:
- "Sent to Jane Doe"
- Date and time "Dec 28, 2025 at 10:30 AM"
- Reference number "TXN-2025122800001"
Create two buttons:
1. "Share Receipt" as an outlined button
2. "Done" as a filled purple button
At the bottom, add a "Transfer another" text link for quick repeat actions.
Make it feel celebratory but professional, like a premium banking app confirmation.
```
---
## Screen 6: All Accounts
```
Design an accounts list screen for a banking app.
Show "My Accounts" as the title with a filter icon on the right.
Create a summary card at the top showing:
- "Total Balance" label
- "$45,750.00" in large text
- Breakdown: Savings $52,500, Loans -$6,750, Shares $0
Add tabs below: All (selected), Savings, Loans, Shares. The selected tab should have an underline indicator.
Group accounts by type:
Savings Accounts section (2):
1. Primary Savings
- Wallet icon in purple circle
- Account number and Active status
- $35,000.00 balance
- Chevron indicating tappable
2. Emergency Fund
- $17,500.00 balance
Loan Accounts section (1):
1. Personal Loan
- Bank icon
- Account number and Active status
- -$6,750.00 in red
- Progress bar showing 80% paid
Add a floating action button (FAB) in the bottom right corner with a plus icon for "Open Account".
```
---
## Screen 7: Activity/Transactions
```
Design a transaction history screen for a banking app.
Show "Activity" as the title with filter and search icons on the right.
Add a date range selector showing "This Month" with dropdown arrows.
Create a summary row showing:
- Income: +$8,500.00 in green
- Expenses: -$2,340.00 in red
- Net: +$6,160.00
Group transactions by date:
Today section:
- Salary Credit from "Employer Inc" at 09:30 AM, +$4,500.00 green
- Bill Payment to "Electric Co" at 08:15 AM, -$150.00 red
Yesterday section:
- Transfer to "Jane Doe" at 03:45 PM, -$500.00 red
- Interest Credit at 12:00 AM, +$45.50 green
Each transaction should show:
- Category icon in a colored circle (green for credit, red for debit)
- Description and merchant/account name
- Time
- Amount with color coding
Add "Load More" at the bottom for pagination.
```
---
## Component Prompts
### Net Worth Hero Card
```
Design a financial summary card for a banking app dashboard.
Use a purple gradient background from dark purple to lighter purple. Make it full width with generous rounded corners (about 28px).
Show "TOTAL NET WORTH" as a small label with an eye icon next to it for privacy toggle.
Display "$45,750.00" as the main balance in large white text, centered.
Below, show "+$1,250.00 this month" with an up arrow to indicate positive change.
Add a subtle divider line.
At the bottom, create 3 equal columns showing: Savings $52,500, Loans -$6,750, Shares $0 - all in white text.
```
### Account Card
```
Design a bank account card component.
White background with subtle shadow, rounded corners (12px).
Layout horizontally:
- Left: A 40px circular icon container with light purple background and wallet icon
- Middle: Account name in medium weight, account number and status in smaller gray text below
- Right: Balance amount aligned right
For loan variant: Add a thin progress bar below the content showing percentage paid.
```
### Transaction Item
```
Design a transaction list item for a banking app.
Create two variants:
1. Credit (money received): Green circular background with down arrow, amount in green with + prefix
2. Debit (money spent): Red circular background with up arrow, amount in red with - prefix
Each shows:
- Category indicator circle on left
- Description and account/merchant name in the middle
- Time in small gray text
- Amount on the right with appropriate color
```
### Quick Action Button
```
Design a quick action button for a banking dashboard.
Create a circular button with light purple background (48px diameter).
Place an icon in the center in darker purple.
Add a label below the circle in small text.
Show 4 variants: Transfer, Deposit, Invest, Beneficiary - each with appropriate icons.
```
---
## Tips for Figma First Draft
1. **Iterate**: Generate once, then refine with follow-up prompts
2. **Colors**: Mention "purple accent #6750A4" for consistency
3. **Reference**: Say "like Revolut" or "Monzo-style" for context
4. **States**: Ask for "show selected and unselected states"
5. **Responsive**: Mention "393px width for mobile" for correct sizing
---
## After Generation
1. Review generated designs for consistency
2. Create a color style library
3. Build component variants
4. Link screens with prototype connections
5. Export and update `FIGMA_LINKS.md`

View File

@ -1,376 +0,0 @@
# Dashboard - Google Stitch Prompts
> **Tool**: [Google Stitch](https://stitch.withgoogle.com)
> **Style**: Material Design 3, Modern Banking
> **Format**: Copy each prompt block directly into Stitch
---
## Design System Reference
```
Primary: #6750A4
Primary Container: #EADDFF
Surface: #FFFBFE
On Surface: #1C1B1F
On Surface Variant: #49454F
Error/Debit: #B3261E
Success/Credit: #2E7D32
Screen Size: 393 x 852 pixels (Android)
Font: Inter
```
---
## Screen 1: Main Dashboard
```
Mobile banking dashboard screen, Material Design 3, fintech app, 393x852px
Header:
- "Good morning, John" greeting, 24px bold, #1C1B1F
- "December 28, 2025" date below, 14px, #49454F
- Right side: notification bell + settings gear icons
Hero Card (Net Worth):
- Full width, purple gradient #6750A4, 28px corner radius
- "TOTAL NET WORTH" label white 12px + eye toggle icon
- Large balance "$45,750.00" white 45px centered
- "+$1,250.00 this month" with up arrow, white 80%
- Divider line white 20%
- Three columns below: Savings $52,500 | Loans -$6,750 | Shares $0
Quick Actions:
- "QUICK ACTIONS" section label
- 4 circular buttons row: Transfer, Deposit, Invest, Beneficiary
- Each: 48px icon in #EADDFF circle, label below
My Accounts Section:
- "MY ACCOUNTS" header + "View All" link right
Account Card 1:
- 40px purple circle with wallet icon
- "Primary Savings" title, "SA-0001234567 • Active" subtitle
- "$35,000.00" balance right, "Interest Rate: 4.5% p.a."
- White card, 12px radius, subtle shadow
Account Card 2:
- Same layout, "Emergency Fund", "$17,500.00"
Account Card 3 (Loan):
- Bank icon, "Personal Loan"
- "-$6,750.00" red text
- Progress bar 80% filled purple on gray
- "Due: Jan 15"
Recent Activity:
- "RECENT ACTIVITY" header + "View All" link
- "Today" date label
Transaction 1:
- Green circle down arrow, "Salary Credit"
- "Primary Savings • 09:30 AM" gray
- "+$4,500.00" green right
Transaction 2:
- Red circle up arrow, "Bill Payment"
- "Primary Savings • 08:15 AM" gray
- "-$150.00" red right
Bottom Navigation:
- 80px height, 5 tabs: Home (selected), Accounts, Transfer, Activity, Profile
- Selected: pill indicator behind icon, primary color
```
---
## Screen 2: Account Detail
```
Savings account detail screen, Material Design 3, banking app, 393x852px
Top Bar:
- Back arrow left
- "Primary Savings" title 22px
- 3-dot menu right
- Surface color background
Balance Hero:
- Large centered "$35,000.00" 36px
- "Available Balance" label below
- "SA-0001234567" account number gray
- "Status: Active • Since: Jan 2023"
Action Buttons Row:
- 4 equal outlined buttons with icons above labels:
- Transfer | Withdraw | Statement | QR Pay
- 8px gap between
Account Details Card:
- "ACCOUNT DETAILS" header
- Two-column key-value pairs:
- Product Name: Savings Plus
- Interest Rate: 4.5% per annum
- Total Deposits: $42,500.00
- Total Withdrawals: $7,500.00
- Total Interest: $1,250.00
- Minimum Balance: $500.00
- Elevated card 12px radius
Transactions Section:
- "TRANSACTIONS" header + Filter dropdown right
- List items with dividers:
- Dec 28: Salary Credit +$4,500.00 green
- Dec 27: Transfer to John -$500.00 red
- Dec 26: Interest Posting +$45.50 green
- Dec 25: ATM Withdrawal -$200.00 red
- Dec 24: Online Purchase -$89.99 red
Charges Section:
- "CHARGES" header
- Monthly Maintenance | Due: Jan 1 | $5.00
- Annual Fee | Paid: Dec 1 | $25.00 checkmark (gray bg)
```
---
## Screen 3: Transfer Flow
```
Money transfer screen, Material Design 3, banking app, 393x852px
Top Bar:
- Back arrow left
- "Transfer Money" title
- Surface background
From Account Selector:
- "FROM ACCOUNT" label 12px gray
- Dropdown showing:
- Wallet icon, "Primary Savings"
- "Available: $35,000.00" green
- Chevron down right
- Outlined container 4px radius
Transfer Type Toggle:
- "TO" label
- Three radio options row:
- My Account | Beneficiary (selected primary) | New Recipient
Beneficiary List:
- "SELECT BENEFICIARY" label
Beneficiary Card 1 (selected):
- Avatar "JD" initials circle
- "Jane Doe" name
- "****4567 • Mifos Bank" masked
- Radio selected indicator
Beneficiary Card 2:
- Avatar "MS" initials
- "Mike Smith"
- "****8901 • Mifos Bank"
- Radio unselected
Amount Input:
- "AMOUNT" label
- Large text field, "$" prefix
- "500.00" value 36px
- Primary color border focused
Remarks Input:
- "REMARKS (Optional)" label
- "Payment for dinner" entered
- Outlined unfocused
Continue Button:
- Full width filled button
- "CONTINUE TO REVIEW"
- Primary #6750A4
- 48px height, full radius
- 16px from bottom
```
---
## Screen 4: Transfer Confirmation
```
Transfer confirmation screen, Material Design 3, banking app, 393x852px
Top Bar:
- Back arrow, "Confirm Transfer" title
Summary Card:
- White elevated card, 16px radius
- Amount large centered "$500.00" 36px
- Arrow down icon
From Section:
- "FROM" label gray
- Wallet icon, "Primary Savings"
- "SA-0001234567"
To Section:
- "TO" label gray
- Avatar "JD", "Jane Doe"
- "****4567 • Mifos Bank"
Details:
- Transfer Type: Beneficiary Transfer
- Remarks: Payment for dinner
- Fee: $0.00
- Total: $500.00
Confirm Button:
- Full width, "CONFIRM TRANSFER"
- Primary filled
Cancel link below, centered gray
```
---
## Screen 5: Transfer Success
```
Transfer success screen, Material Design 3, banking app, 393x852px
Center content:
Success Animation:
- Large green checkmark 120px
- Circular green (#2E7D32) background with pulse
- Confetti particles around
Title:
- "Transfer Successful!" 28px bold
Amount:
- "$500.00" 36px
Details:
- "Sent to Jane Doe"
- "Dec 28, 2025 at 10:30 AM"
- Reference: TXN-2025122800001
Action Buttons:
- "Share Receipt" outlined button
- "Done" filled primary button
Bottom:
- "Transfer another" text link
```
---
## Screen 6: All Accounts
```
Accounts list screen, Material Design 3, banking app, 393x852px
Top Bar:
- "My Accounts" title 22px
- Filter icon right
Summary Card:
- "TOTAL BALANCE" label
- "$45,750.00" large
- Savings: $52,500 | Loans: -$6,750 | Shares: $0
Tabs:
- All | Savings | Loans | Shares
- "All" selected with underline indicator
Account List:
Savings Section:
- "SAVINGS ACCOUNTS (2)" header
Card 1:
- Wallet icon purple circle
- "Primary Savings"
- "SA-0001234567 • Active"
- "$35,000.00"
- Chevron right
Card 2:
- "Emergency Fund"
- "$17,500.00"
Loans Section:
- "LOAN ACCOUNTS (1)" header
Card:
- Bank icon
- "Personal Loan"
- "LA-0009876543 • Active"
- "-$6,750.00" red
- Progress 80%
FAB:
- Bottom right floating action button
- Plus icon, primary color
- "Open Account" label on long press
```
---
## Components
### Net Worth Card
```
Financial summary card component, Material Design 3:
- 361px width, auto height ~180px
- Gradient #6750A4 to #7E67B0
- 28px corner radius, 20px padding
- "TOTAL NET WORTH" white 12px + eye icon
- "$45,750.00" white 45px centered
- "+$1,250.00 this month" white 80%
- Divider white 20%
- 3 columns: Savings $52,500 | Loans -$6,750 | Shares $0
- Level 2 shadow
```
### Account Card
```
Bank account card component, Material Design 3:
- 361px width, ~88px height
- White #FFFBFE, 12px radius, level 1 shadow
- 16px padding
- Left: 40px icon circle #EADDFF
- Center: Title 16px, subtitle 12px gray
- Right: Balance 16px
- Loan variant: Add progress bar below
```
### Transaction Item
```
Transaction list item, Material Design 3:
- 361px width, 72px height
- Left: 40px indicator circle
- Credit: green #C8E6C9 bg, down arrow #2E7D32
- Debit: red #F9DEDC bg, up arrow #B3261E
- Center: Description 16px, Account+time 12px gray
- Right: Amount colored (green credit, red debit)
```
### Quick Action Button
```
Quick action circular button, Material Design 3:
- 64px total height
- 48px icon circle, #EADDFF background
- Icon 24px, #6750A4
- Label below 12px, #49454F
- Tap state: ripple effect
```
---
## Quick Start
1. Open [stitch.withgoogle.com](https://stitch.withgoogle.com)
2. Create project "Mifos Mobile - Dashboard"
3. Copy each screen prompt → Generate
4. Generate components separately for reuse
5. Export all to Figma when done

View File

@ -1,294 +0,0 @@
{
"feature": "Dashboard",
"generated": "2025-12-28",
"source": "features/dashboard/SPEC.md",
"tokens": {
"colors": {
"primary": "#6750A4",
"onPrimary": "#FFFFFF",
"primaryContainer": "#EADDFF",
"onPrimaryContainer": "#21005D",
"secondary": "#625B71",
"onSecondary": "#FFFFFF",
"secondaryContainer": "#E8DEF8",
"surface": "#FFFBFE",
"surfaceContainer": "#F3EDF7",
"surfaceContainerHigh": "#ECE6F0",
"onSurface": "#1C1B1F",
"onSurfaceVariant": "#49454F",
"outline": "#79747E",
"outlineVariant": "#CAC4D0",
"error": "#B3261E",
"onError": "#FFFFFF",
"errorContainer": "#F9DEDC",
"success": "#2E7D32",
"onSuccess": "#FFFFFF",
"successContainer": "#C8E6C9"
},
"typography": {
"displayLarge": {
"size": 57,
"weight": 400,
"lineHeight": 64,
"letterSpacing": -0.25
},
"displayMedium": {
"size": 45,
"weight": 400,
"lineHeight": 52,
"letterSpacing": 0
},
"displaySmall": {
"size": 36,
"weight": 400,
"lineHeight": 44,
"letterSpacing": 0
},
"headlineMedium": {
"size": 28,
"weight": 400,
"lineHeight": 36,
"letterSpacing": 0
},
"headlineSmall": {
"size": 24,
"weight": 400,
"lineHeight": 32,
"letterSpacing": 0
},
"titleLarge": {
"size": 22,
"weight": 400,
"lineHeight": 28,
"letterSpacing": 0
},
"titleMedium": {
"size": 16,
"weight": 500,
"lineHeight": 24,
"letterSpacing": 0.15
},
"bodyLarge": {
"size": 16,
"weight": 400,
"lineHeight": 24,
"letterSpacing": 0.5
},
"bodyMedium": {
"size": 14,
"weight": 400,
"lineHeight": 20,
"letterSpacing": 0.25
},
"bodySmall": {
"size": 12,
"weight": 400,
"lineHeight": 16,
"letterSpacing": 0.4
},
"labelLarge": {
"size": 14,
"weight": 500,
"lineHeight": 20,
"letterSpacing": 0.1
},
"labelMedium": {
"size": 12,
"weight": 500,
"lineHeight": 16,
"letterSpacing": 0.5
}
},
"spacing": {
"none": 0,
"xs": 4,
"sm": 8,
"md": 16,
"lg": 24,
"xl": 32,
"xxl": 48
},
"radius": {
"none": 0,
"xs": 4,
"sm": 8,
"md": 12,
"lg": 16,
"xl": 28,
"full": 9999
},
"elevation": {
"level0": "none",
"level1": "0 1px 3px 1px rgba(0,0,0,0.15)",
"level2": "0 2px 6px 2px rgba(0,0,0,0.15)",
"level3": "0 4px 8px 3px rgba(0,0,0,0.15)"
},
"screen": {
"width": 393,
"height": 852
}
},
"components": [
{
"name": "NetWorthCard",
"type": "card",
"properties": {
"background": "primary",
"radius": "xl",
"padding": {
"horizontal": 24,
"vertical": 20
},
"elements": [
{"type": "label", "text": "TOTAL NET WORTH", "style": "labelMedium", "color": "onPrimary"},
{"type": "icon", "name": "visibility", "size": 24, "color": "onPrimary"},
{"type": "text", "style": "displayMedium", "color": "onPrimary"},
{"type": "text", "style": "bodyMedium", "color": "onPrimary", "opacity": 0.8},
{"type": "row", "columns": ["Savings", "Loans", "Shares"]}
]
}
},
{
"name": "QuickActions",
"type": "row",
"properties": {
"itemCount": 4,
"gap": "sm",
"items": [
{"icon": "send", "label": "Transfer"},
{"icon": "download", "label": "Deposit"},
{"icon": "trending_up", "label": "Invest"},
{"icon": "people", "label": "Beneficiary"}
]
}
},
{
"name": "AccountCard",
"type": "card",
"properties": {
"background": "surface",
"radius": "md",
"elevation": "level1",
"padding": "md",
"elements": [
{"type": "avatar", "size": 40, "background": "primaryContainer"},
{"type": "column", "flex": 1, "children": [
{"type": "text", "style": "titleMedium", "color": "onSurface"},
{"type": "text", "style": "bodySmall", "color": "onSurfaceVariant"}
]},
{"type": "text", "style": "titleMedium", "color": "onSurface"}
]
}
},
{
"name": "TransactionItem",
"type": "listItem",
"properties": {
"height": 72,
"padding": {"vertical": 8, "horizontal": 0},
"elements": [
{"type": "indicator", "size": 40, "variants": {
"credit": {"background": "successContainer", "icon": "arrow_downward", "iconColor": "success"},
"debit": {"background": "errorContainer", "icon": "arrow_upward", "iconColor": "error"}
}},
{"type": "column", "flex": 1, "children": [
{"type": "text", "style": "bodyLarge", "color": "onSurface"},
{"type": "text", "style": "bodySmall", "color": "onSurfaceVariant"}
]},
{"type": "amount", "style": "titleMedium", "colorByType": true}
]
}
},
{
"name": "BottomNavigation",
"type": "navigation",
"properties": {
"height": 80,
"background": "surfaceContainer",
"items": [
{"icon": "home", "label": "Home"},
{"icon": "credit_card", "label": "Accounts"},
{"icon": "send", "label": "Transfer"},
{"icon": "bar_chart", "label": "Activity"},
{"icon": "person", "label": "Profile"}
],
"selectedIndicator": {
"background": "secondaryContainer",
"radius": "lg",
"width": 64,
"height": 32
}
}
},
{
"name": "TopBar",
"type": "appBar",
"properties": {
"height": 64,
"background": "surface",
"elements": [
{"type": "navigation", "icon": "arrow_back", "optional": true},
{"type": "title", "style": "titleLarge", "color": "onSurface"},
{"type": "actions", "icons": ["notifications", "settings"]}
]
}
},
{
"name": "SectionHeader",
"type": "header",
"properties": {
"padding": {"top": "md", "bottom": "sm"},
"elements": [
{"type": "text", "style": "titleMedium", "color": "onSurface"},
{"type": "link", "text": "View All →", "style": "labelMedium", "color": "primary"}
]
}
}
],
"screens": [
{
"name": "DashboardScreen",
"route": "/dashboard",
"layout": "vertical",
"components": [
"TopBar",
"Greeting",
"NetWorthCard",
"QuickActions",
"SectionHeader:MY ACCOUNTS",
"AccountCard:savings",
"AccountCard:loan",
"SectionHeader:RECENT ACTIVITY",
"TransactionItem:list",
"BottomNavigation"
]
},
{
"name": "AccountDetailScreen",
"route": "/account/:id",
"layout": "vertical",
"components": [
"TopBar:back",
"BalanceHero",
"ActionButtons",
"AccountDetailsCard",
"TransactionsList",
"ChargesSection"
]
},
{
"name": "TransferScreen",
"route": "/transfer",
"layout": "vertical",
"components": [
"TopBar:back",
"AccountSelector:from",
"TransferTypeToggle",
"BeneficiaryList",
"AmountInput",
"RemarksInput",
"ContinueButton"
]
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Some files were not shown because too many files have changed in this diff Show More