# Implementation Plan: unified-app ## Overview This plan consolidates the Reports App and Data Entry App frontends into a single unified SPA. The implementation follows a pragmatic monolith approach with module isolation through error boundaries and lazy loading. **Key principles:** - Single build, single IIS site deployment - Module isolation via error boundaries (errors in one module don't crash the other) - Lazy loading for each module (only load what the user navigates to) - Shared components from `src/shared/` (auth, companies, period selectors) - CSS system from reports-app preserved and enhanced **Worktree location:** `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app` --- ## Phase 1: Project Setup (0.5 days) ### Task 1: Create Root Directory Structure **Objective**: Set up the foundational directory structure for the unified app at the repository root. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/` (create directory) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/` (create directory) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/` (create directory) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/` (create directory) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/` (create directory) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/config/` (create directory) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/router/` (create directory) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/assets/` (create directory) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/public/` (create directory) **Description**: Create the following directory structure at the repository root (not inside reports-app or data-entry-app): ``` src/ modules/ reports/ views/ stores/ services/ data-entry/ views/ receipts/ components/ ocr/ stores/ services/ shared/ components/ layout/ stores/ styles/ layout/ config/ router/ assets/ css/ core/ components/ patterns/ layout/ utilities/ vendor/ public/ ``` **Dependencies**: None **Completion Criteria**: - [x] All directories created - [x] Directory structure matches specification --- ### Task 2: Create package.json with Merged Dependencies **Objective**: Create unified package.json combining dependencies from both apps. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/package.json` (create) **Description**: Merge dependencies from both `reports-app/frontend/package.json` and `data-entry-app/frontend/package.json`: **Dependencies to include:** - `vue`: ^3.4.0 - `vue-router`: ^4.2.5 - `pinia`: ^2.1.7 - `axios`: ^1.6.5 (use higher version) - `primevue`: ^3.48.0 (use higher version) - `primeicons`: ^6.0.1 - `chart.js`: ^4.5.0 (reports only) - `vue-chartjs`: ^5.3.2 (reports only) - `date-fns`: ^2.30.0 - `jspdf`: ^3.0.1 - `jspdf-autotable`: ^5.0.2 - `xlsx`: ^0.18.5 - `qrcode.vue`: ^3.6.0 **DevDependencies:** - `@vitejs/plugin-vue`: ^5.0.0 - `vite`: ^5.0.10 - `@playwright/test`: ^1.54.2 - `eslint`: ^8.56.0 - `eslint-plugin-vue`: ^9.20.0 - `prettier`: ^3.1.1 **Scripts:** - `dev`: vite - `build`: vite build - `preview`: vite preview - `lint`: eslint src/ --ext .vue,.js --fix - `test:e2e`: playwright test **Dependencies**: Task 1 **Completion Criteria**: - [x] package.json created with all dependencies - [x] Scripts defined correctly - [x] `npm install` succeeds --- ### Task 3: Create vite.config.js with Dual Proxy and Lazy Loading **Objective**: Configure Vite for unified app with proxies to both backends. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/vite.config.js` (create) **Description**: Create Vite configuration with: 1. **Dual proxy configuration:** - `/api/reports/*` -> `http://localhost:8001/api/*` - `/api/data-entry/*` -> `http://localhost:8003/api/*` - `/uploads` -> `http://localhost:8003` 2. **Aliases:** - `@` -> `./src` - `@shared` -> `./src/shared` - `@reports` -> `./src/modules/reports` - `@data-entry` -> `./src/modules/data-entry` 3. **Build configuration:** - `base`: `/` (single site, no subdirectory) - Manual chunks for vendors (vue, primevue, charts, exports) - Source maps enabled - Cache busting with hashes 4. **dedupe** for Vue, vue-router, pinia, primevue 5. **WSL2 file watching** (usePolling: true) Reference: `reports-app/frontend/vite.config.js` for htmlTimestampPlugin and build settings. **Dependencies**: Task 1 **Completion Criteria**: - [x] Vite config created with dual proxy - [x] All aliases defined - [x] Manual chunks configured - [x] `npm run dev` starts successfully --- ### Task 4: Copy CSS System from Reports App **Objective**: Migrate the complete CSS design system to the unified app. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/assets/css/` (copy entire directory) **Description**: Copy the entire CSS directory from `reports-app/frontend/src/assets/css/` to `src/assets/css/`: - `core/` - Design tokens (tokens.css) - `components/` - Component patterns (cards.css, badges.css, stats.css, etc.) - `patterns/` - Interactive patterns - `layout/` - Page structure - `utilities/` - Utility classes - `vendor/` - PrimeVue overrides - `main.css` - Main import file - `global.css` - Global styles - `mobile.css` - Mobile responsive styles This is the authoritative CSS system that both modules will use. **Dependencies**: Task 1 **Completion Criteria**: - [x] All CSS files copied - [x] Directory structure preserved - [x] `main.css` imports all other CSS files correctly --- ### Task 5: Copy Shared Frontend Components and Stores **Objective**: Migrate shared components to unified app's shared directory. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/components/LoginView.vue` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/components/CompanySelector.vue` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/components/PeriodSelector.vue` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/components/layout/AppHeader.vue` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/components/layout/SlideMenu.vue` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/stores/auth.js` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/stores/companies.js` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/stores/accountingPeriod.js` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/styles/login.css` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/styles/layout/header.css` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/styles/layout/navigation.css` (copy) **Description**: Copy from `shared/frontend/`: 1. Components: `LoginView.vue`, `CompanySelector.vue`, `PeriodSelector.vue`, `layout/AppHeader.vue`, `layout/SlideMenu.vue` 2. Stores: `auth.js`, `companies.js`, `accountingPeriod.js` 3. Styles: `login.css`, `layout/header.css`, `layout/navigation.css` Update import paths in components to use relative paths within `src/shared/`. **Dependencies**: Task 1 **Completion Criteria**: - [x] All shared components copied - [x] All shared stores copied - [x] All shared styles copied - [x] Import paths updated to work from new location --- ### Task 6: Create .env.example and public/index.html **Objective**: Create environment template and HTML entry point. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/.env.example` (create) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/public/index.html` (create) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/public/favicon.ico` (copy from reports-app if exists) **Description**: 1. Create `.env.example`: ``` # API URLs (development) VITE_REPORTS_API_URL=http://localhost:8001/api VITE_DATA_ENTRY_API_URL=http://localhost:8003/api # Feature flags VITE_FEATURE_REPORTS=true VITE_FEATURE_DATA_ENTRY=true ``` 2. Create `public/index.html` (or use Vite's default index.html in root): ```html ROA2WEB - Unified App
``` **Dependencies**: Task 1 **Completion Criteria**: - [x] .env.example created - [x] index.html created with proper meta tags - [x] Build timestamp placeholder present --- ## Phase 2: Module Migration (1 day) ### Task 7: Migrate Reports Module Views **Objective**: Copy and adapt Reports views to the modules directory. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/views/DashboardView.vue` (copy and adapt) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/views/InvoicesView.vue` (copy and adapt) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/views/BankCashRegisterView.vue` (copy and adapt) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/views/TrialBalanceView.vue` (copy and adapt) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/views/TelegramView.vue` (copy and adapt) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/views/CacheStatsView.vue` (copy and adapt) **Description**: Copy views from `reports-app/frontend/src/views/` to `src/modules/reports/views/`: - DashboardView.vue - InvoicesView.vue - BankCashRegisterView.vue - TrialBalanceView.vue - TelegramView.vue - CacheStatsView.vue **DO NOT copy LoginView.vue** - use shared LoginView. Update imports: - Change `@/stores/xxx` to `@reports/stores/xxx` for module-specific stores - Change `@/stores/auth` to `@shared/stores/auth` - Change `@/stores/companies` to `@shared/stores/companies` - Change `@/stores/accountingPeriod` to `@shared/stores/accountingPeriod` **Dependencies**: Task 4, Task 5 **Completion Criteria**: - [x] All 6 views copied - [x] Import paths updated - [x] No references to old shared path (`../../../shared/`) --- ### Task 8: Migrate Reports Module Stores **Objective**: Copy and adapt Reports stores to the modules directory. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/stores/dashboard.js` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/stores/invoices.js` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/stores/treasury.js` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/stores/trialBalance.js` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/stores/cacheStore.js` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/stores/index.js` (copy and adapt) **Description**: Copy module-specific stores from `reports-app/frontend/src/stores/`: - dashboard.js - invoices.js - treasury.js - trialBalance.js - cacheStore.js - index.js (barrel export) **DO NOT copy auth.js, companies.js, accountingPeriod.js** - these are in shared. Update any internal imports to use module paths. **Dependencies**: Task 5 **Completion Criteria**: - [x] All 6 store files copied - [x] No references to shared stores (auth, companies, period) - [x] index.js exports all module stores --- ### Task 9: Create Reports Module API Service **Objective**: Create API service for Reports module with `/api/reports/` prefix. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/services/api.js` (create/adapt) **Description**: Create or adapt the API service from `reports-app/frontend/src/services/api.js`: 1. Base URL: `/api/reports` (proxied to port 8001) 2. Include auth token interceptor 3. Include response error handler 4. Export configured axios instance Example structure: ```javascript import axios from 'axios' const api = axios.create({ baseURL: '/api/reports', headers: { 'Content-Type': 'application/json' } }) // Request interceptor for auth token api.interceptors.request.use((config) => { const token = localStorage.getItem('access_token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) export default api ``` **Dependencies**: Task 1 **Completion Criteria**: - [x] API service created with `/api/reports` base URL - [x] Auth token interceptor configured - [x] Error handling interceptor configured --- ### Task 10: Migrate Data Entry Module Views **Objective**: Copy and adapt Data Entry views to the modules directory. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/views/receipts/ReceiptsListView.vue` (copy and adapt) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/views/receipts/ReceiptCreateView.vue` (copy and adapt) **Description**: Copy views from `data-entry-app/frontend/src/views/receipts/`: - ReceiptsListView.vue - ReceiptCreateView.vue **DO NOT copy LoginView.vue** - use shared LoginView. Update imports: - Change `@/stores/xxx` to `@data-entry/stores/xxx` for module-specific stores - Change `@/stores/auth` to `@shared/stores/auth` - Change `@/stores/companies` to `@shared/stores/companies` - Change `@/stores/accountingPeriod` to `@shared/stores/accountingPeriod` - Change `@/components/xxx` to `@data-entry/components/xxx` - Change `@/services/api` to `@data-entry/services/api` **Dependencies**: Task 4, Task 5 **Completion Criteria**: - [x] Both receipt views copied - [x] Import paths updated - [x] No references to old shared path --- ### Task 11: Migrate Data Entry Module Components **Objective**: Copy Data Entry specific components (OCR). **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/components/ocr/OCRUploadZone.vue` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/components/ocr/OCRPreview.vue` (copy) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/components/ocr/OCRConfidenceIndicator.vue` (copy) **Description**: Copy OCR components from `data-entry-app/frontend/src/components/ocr/`: - OCRUploadZone.vue - OCRPreview.vue - OCRConfidenceIndicator.vue Update any imports to use the new module paths. **Dependencies**: Task 1 **Completion Criteria**: - [x] All 3 OCR components copied - [x] Import paths updated - [x] Components work independently --- ### Task 12: Migrate Data Entry Module Stores **Objective**: Copy Data Entry specific stores. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/stores/receiptsStore.js` (copy and adapt) **Description**: Copy from `data-entry-app/frontend/src/stores/`: - receiptsStore.js **DO NOT copy auth.js, companies.js, accountingPeriod.js** - these are in shared. Update imports: - API service import to `@data-entry/services/api` **Dependencies**: Task 5 **Completion Criteria**: - [x] receiptsStore.js copied - [x] Import paths updated - [x] No duplicate shared stores --- ### Task 13: Create Data Entry Module API Service **Objective**: Create API service for Data Entry module with `/api/data-entry/` prefix. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/services/api.js` (create/adapt) **Description**: Create or adapt the API service from `data-entry-app/frontend/src/services/api.js`: 1. Base URL: `/api/data-entry` (proxied to port 8003) 2. Include auth token interceptor 3. Include `X-Selected-Company` header injection 4. Include response error handler 5. Export configured axios instance Reference the existing `data-entry-app/frontend/src/services/api.js` for company header logic. **Dependencies**: Task 1 **Completion Criteria**: - [x] API service created with `/api/data-entry` base URL - [x] Auth token interceptor configured - [x] Company header interceptor configured --- ### Task 14: Merge and Adapt CSS from Data Entry **Objective**: Integrate any unique Data Entry CSS into the unified CSS system. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/assets/css/modules/data-entry.css` (create if needed) **Description**: 1. Review `data-entry-app/frontend/src/assets/css/main.css` for unique styles 2. Extract any styles not already covered by the reports-app CSS system 3. Add to a new `modules/data-entry.css` file if needed 4. Import in main.css Note: Data Entry currently uses `lara-light-blue` theme while Reports uses `saga-blue`. Decision: Use `saga-blue` (reports-app theme) for consistency as per spec. **Dependencies**: Task 4 **Completion Criteria**: - [x] Data Entry unique styles identified - [x] Styles merged without conflicts - [x] PrimeVue theme standardized to saga-blue --- ## Phase 3: Routing & Navigation (0.5 days) ### Task 15: Create Unified Router Configuration **Objective**: Create unified Vue Router with lazy loading for both modules. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/router/index.js` (create) **Description**: Create unified router with: 1. **Login route** (not lazy loaded - immediate access needed): ```javascript { path: '/login', name: 'Login', component: () => import('@shared/components/LoginView.vue'), meta: { requiresAuth: false, title: 'Autentificare - ROA2WEB' } } ``` 2. **Reports module routes** (lazy loaded): ```javascript { path: '/reports', component: () => import('@/modules/reports/ReportsLayout.vue'), children: [ { path: 'dashboard', name: 'Dashboard', component: () => import('@reports/views/DashboardView.vue') }, { path: 'invoices', name: 'Invoices', component: () => import('@reports/views/InvoicesView.vue') }, { path: 'bank-cash', name: 'BankCash', component: () => import('@reports/views/BankCashRegisterView.vue') }, { path: 'trial-balance', name: 'TrialBalance', component: () => import('@reports/views/TrialBalanceView.vue') }, { path: 'telegram', name: 'Telegram', component: () => import('@reports/views/TelegramView.vue') }, { path: 'cache-stats', name: 'CacheStats', component: () => import('@reports/views/CacheStatsView.vue') }, ] } ``` 3. **Data Entry module routes** (lazy loaded): ```javascript { path: '/data-entry', component: () => import('@/modules/data-entry/DataEntryLayout.vue'), children: [ { path: '', name: 'ReceiptsList', component: () => import('@data-entry/views/receipts/ReceiptsListView.vue') }, { path: 'create', name: 'ReceiptCreate', component: () => import('@data-entry/views/receipts/ReceiptCreateView.vue') }, { path: ':id', name: 'ReceiptDetail', component: () => import('@data-entry/views/receipts/ReceiptCreateView.vue') }, { path: ':id/edit', name: 'ReceiptEdit', component: () => import('@data-entry/views/receipts/ReceiptCreateView.vue') }, ] } ``` 4. **Redirects**: - `/` -> `/reports/dashboard` - `/:pathMatch(.*)*` -> `/reports/dashboard` 5. **Navigation guards**: - Check authentication before protected routes - Set page title from route meta - Scroll to top after navigation **Dependencies**: Task 7, Task 10 **Completion Criteria**: - [x] All routes defined with lazy loading - [x] Navigation guards implemented - [x] Redirects configured - [x] Page titles set from meta --- ### Task 16: Create Menu Configuration **Objective**: Create unified menu configuration for all modules. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/config/menu.js` (create) **Description**: Create menu configuration with sections: ```javascript export const menuSections = [ { title: 'Rapoarte', items: [ { to: '/reports/dashboard', icon: 'pi pi-home', label: 'Dashboard' }, { to: '/reports/invoices', icon: 'pi pi-file', label: 'Facturi' }, { to: '/reports/bank-cash', icon: 'pi pi-money-bill', label: 'Casa si Banca' }, { to: '/reports/trial-balance', icon: 'pi pi-calculator', label: 'Balanta de Verificare' } ] }, { title: 'Introduceri Date', items: [ { to: '/data-entry', icon: 'pi pi-list', label: 'Lista Bonuri' }, { to: '/data-entry/create', icon: 'pi pi-plus', label: 'Bon Nou' } ] }, { title: 'Sistem', items: [ { to: '/reports/telegram', icon: 'pi pi-telegram', label: 'Telegram Bot' }, { to: '/reports/cache-stats', icon: 'pi pi-chart-bar', label: 'Statistici Cache' } ] } ] ``` **Dependencies**: None **Completion Criteria**: - [x] Menu configuration created - [x] All routes represented - [x] Icons assigned correctly --- ### Task 17: Create Feature Flags Configuration **Objective**: Create feature flags for module enable/disable. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/config/features.js` (create) **Description**: Create feature flags configuration: ```javascript export const features = { reports: { enabled: import.meta.env.VITE_FEATURE_REPORTS !== 'false', modules: { dashboard: true, invoices: true, bankCash: true, trialBalance: true, telegram: true, cacheStats: true } }, dataEntry: { enabled: import.meta.env.VITE_FEATURE_DATA_ENTRY !== 'false', modules: { receipts: true, ocr: true } } } export function isFeatureEnabled(module, subModule = null) { if (!features[module]?.enabled) return false if (subModule && !features[module]?.modules?.[subModule]) return false return true } export function getEnabledMenuSections(menuSections) { return menuSections.filter(section => { if (section.title === 'Rapoarte') return features.reports.enabled if (section.title === 'Introduceri Date') return features.dataEntry.enabled return true // System section always visible }) } ``` **Dependencies**: Task 16 **Completion Criteria**: - [x] Feature flags created - [x] Environment variable support - [x] Helper functions for filtering menu --- ### Task 18: Create App.vue Root Component **Objective**: Create unified App.vue with menu integration. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/App.vue` (create) **Description**: Create App.vue that: 1. Shows AppHeader and SlideMenu when authenticated 2. Uses unified menu configuration from `config/menu.js` 3. Filters menu based on feature flags 4. Handles company/period changes 5. Handles user logout (clears all stores) 6. Uses Toast and ConfirmDialog globally Reference `reports-app/frontend/src/App.vue` for structure but adapt for: - Using `@shared/` components - Using unified menu - Using shared stores via aliases **Dependencies**: Task 5, Task 15, Task 16, Task 17 **Completion Criteria**: - [x] App.vue created - [x] Header and SlideMenu integrated - [x] Menu sections from config - [x] Company/period handlers work - [x] Logout clears all stores --- ### Task 19: Create main.js Entry Point **Objective**: Create unified main.js with PrimeVue setup. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/main.js` (create) **Description**: Create main.js that: 1. Creates Vue app 2. Sets up Pinia store 3. Sets up Vue Router 4. Configures PrimeVue with `saga-blue` theme 5. Registers ToastService, ConfirmationService 6. Registers common PrimeVue components globally 7. Imports unified CSS (`./assets/css/main.css`) Merge component registrations from both apps: - From reports: Button, InputText, Password, DataTable, Column, Card, Toast, ConfirmDialog, Menu, Menubar, Badge, Tag, Dropdown, AutoComplete, Calendar, ProgressSpinner, Dialog - From data-entry: InputNumber, Textarea, FileUpload, Image, TabView, TabPanel, Checkbox, RadioButton, Toolbar, Divider, Message **Dependencies**: Task 2, Task 4, Task 15 **Completion Criteria**: - [x] main.js created - [x] All PrimeVue components registered - [x] PrimeVue theme set to saga-blue - [x] CSS imports correct - [x] App mounts successfully --- ## Phase 4: Error Boundaries & Resilience (0.25 days) ### Task 20: Create ErrorBoundary Component **Objective**: Create reusable error boundary component. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/components/ErrorBoundary.vue` (create) **Description**: Create ErrorBoundary.vue component that: 1. Uses `onErrorCaptured` to catch child component errors 2. Displays user-friendly error message in Romanian 3. Provides "Retry" button (reloads page) 4. Provides "Go to Dashboard" button 5. Logs error details to console 6. Returns `false` from onErrorCaptured to prevent propagation Template structure: ```vue ``` **Dependencies**: Task 5 **Completion Criteria**: - [x] ErrorBoundary component created - [x] Catches errors from children - [x] Shows user-friendly message - [x] Retry and navigation buttons work --- ### Task 21: Create ReportsLayout Module Wrapper **Objective**: Create layout wrapper with error boundary for Reports module. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/reports/ReportsLayout.vue` (create) **Description**: Create ReportsLayout.vue that wraps module routes with ErrorBoundary: ```vue ``` This ensures errors in Reports views don't crash the entire app. **Dependencies**: Task 20 **Completion Criteria**: - [x] ReportsLayout created - [x] ErrorBoundary wraps router-view - [x] Module name set correctly --- ### Task 22: Create DataEntryLayout Module Wrapper **Objective**: Create layout wrapper with error boundary for Data Entry module. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/modules/data-entry/DataEntryLayout.vue` (create) **Description**: Create DataEntryLayout.vue that wraps module routes with ErrorBoundary: ```vue ``` **Dependencies**: Task 20 **Completion Criteria**: - [x] DataEntryLayout created - [x] ErrorBoundary wraps router-view - [x] Module name set correctly --- ### Task 23: Add Loading States for Lazy Routes **Objective**: Add loading indicators during module loading. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/components/ModuleLoading.vue` (create) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/router/index.js` (update) **Description**: 1. Create ModuleLoading.vue component with ProgressSpinner 2. Configure router to show loading state during async component loading Using Vue Router's built-in async component handling: ```javascript component: defineAsyncComponent({ loader: () => import('@reports/views/DashboardView.vue'), loadingComponent: ModuleLoading, delay: 200, timeout: 10000 }) ``` Or use Suspense in layout components. **Dependencies**: Task 15, Task 20 **Completion Criteria**: - [x] Loading component created - [x] Shown during module lazy loading - [x] Reasonable delay before showing --- ## Phase 5: Build & Deployment (0.25 days) ### Task 24: Create IIS web.config for Production **Objective**: Create web.config with URL rewrite rules for IIS deployment. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/public/web.config` (create) **Description**: Create web.config with: 1. **URL Rewrite Rules**: - `/api/reports/*` -> `http://localhost:8001/api/*` - `/api/data-entry/*` -> `http://localhost:8003/api/*` - `/uploads/*` -> `http://localhost:8003/uploads/*` - SPA fallback: all other routes -> `/index.html` 2. **Static file handling** 3. **Cache headers for assets** 4. **MIME types for modern files** ```xml ``` **Dependencies**: None **Completion Criteria**: - [x] web.config created - [x] API proxy rules correct - [x] SPA fallback configured --- ### Task 25: Verify Build and Bundle Splitting **Objective**: Run production build and verify output. **Files**: - (verification task, no file modifications) **Description**: 1. Run `npm run build` 2. Verify `dist/` output: - `assets/vendor-core.[hash].js` (vue, router, pinia) - `assets/vendor-primevue.[hash].js` (primevue components) - `assets/vendor-utils.[hash].js` (axios, date-fns) - `assets/vendor-charts.[hash].js` (chart.js - lazy) - `assets/vendor-export.[hash].js` (xlsx, jspdf - lazy) - Module chunks for reports and data-entry - CSS chunk 3. Check total bundle size <= sum of old apps 4. Verify source maps generated **Dependencies**: Tasks 1-23 **Completion Criteria**: - [x] Build completes without errors - [x] Expected chunks generated - [x] Bundle size acceptable - [x] Source maps present --- ### Task 26: Create README Documentation **Objective**: Create README for the unified app. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/unified-app-README.md` (create, will be moved to README.md later) **Description**: Create documentation covering: 1. **Overview**: Unified SPA combining Reports and Data Entry 2. **Quick Start**: - `npm install` - `npm run dev` (requires both backends running) - `npm run build` 3. **Architecture**: - Module structure - Shared components - Error boundaries 4. **URL Structure** 5. **Deployment**: - IIS configuration - Proxy setup 6. **Feature Flags** 7. **Development Guide**: - Adding new routes - Adding new components - CSS system reference **Dependencies**: None **Completion Criteria**: - [x] README covers all sections - [x] Quick start instructions work - [x] Architecture explained clearly --- ### Task 27: Update Shared Stores for Dual API Support **Objective**: Ensure shared stores work with both API endpoints. **Files**: - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/stores/auth.js` (update) - `/mnt/e/proiecte/ab-worktrees/roa2web-unified-app/src/shared/stores/companies.js` (update) **Description**: The shared stores (auth, companies) need to work with both backends. Since authentication is handled by the Reports backend (port 8001), update: 1. **auth.js**: Use `/api/reports/auth/` for login/logout 2. **companies.js**: Use `/api/reports/companies/` for company list Ensure the API base URL is correctly configured for the unified app's proxy setup. **Dependencies**: Task 5, Task 3 **Completion Criteria**: - [x] Auth store uses correct API path - [x] Companies store uses correct API path - [x] Login/logout flow works --- ### Task 28: End-to-End Integration Test **Objective**: Verify the complete unified app works. **Files**: - (verification task, manual testing) **Description**: Manual testing checklist: 1. **Dev Server**: - [ ] `npm run dev` starts on port 3000 - [ ] No console errors on load 2. **Login Flow**: - [ ] Navigate to `/login` - [ ] Login with valid credentials - [ ] Redirected to `/reports/dashboard` 3. **Reports Module**: - [ ] Dashboard loads with data - [ ] Navigate to Invoices - [ ] Navigate to Bank/Cash - [ ] Navigate to Trial Balance - [ ] Navigate to Telegram - [ ] Navigate to Cache Stats 4. **Data Entry Module**: - [ ] Navigate to `/data-entry` (Receipts List) - [ ] Navigate to `/data-entry/create` (Create Receipt) - [ ] Company selector preserved from Reports 5. **Module Switching**: - [ ] Switch from Reports to Data Entry - [ ] Switch from Data Entry to Reports - [ ] Selected company/period preserved 6. **Error Boundary**: - [ ] Intentionally break a component - [ ] Error shows in that module only - [ ] Other module still works 7. **Logout**: - [ ] Logout works - [ ] Redirected to login - [ ] All stores cleared **Dependencies**: All previous tasks **Completion Criteria**: - [ ] All manual tests pass - [ ] No console errors - [ ] No visual regressions --- ## Testing Strategy ### During Implementation - After each task, verify no import/build errors - Test changed components individually - Check browser console for errors ### Final Validation - Run `npm run build` - must succeed - Run `npm run preview` - test production build - Test on different screen sizes (mobile, tablet, desktop) - Verify lazy loading with Network tab (modules load on demand) --- ## Risk Mitigation | Risk | Detection | Response | |------|-----------|----------| | CSS conflicts between modules | Visual testing shows wrong styles | Use scoped styles or module-specific CSS files | | Import path errors | Build fails or runtime errors | Check all import aliases in vite.config.js | | PrimeVue theme inconsistency | Different component styles | Ensure only saga-blue theme imported | | Shared store contamination | Data appears in wrong module | Keep module stores separate, only use shared for auth/company/period | | Lazy loading not working | Large initial bundle | Verify dynamic imports in router | | Error boundary not catching | App crashes on error | Test with intentional errors | --- ## Notes for Implementation 1. **Always use absolute paths** from worktree root when creating files 2. **Test incrementally** - don't wait until the end to test 3. **Preserve existing functionality** - this is a migration, not a rewrite 4. **Reference existing files** - use reports-app as the primary reference 5. **Use saga-blue theme** consistently (reports-app theme) 6. **Login always uses Reports API** (port 8001) for authentication 7. **Keep module stores isolated** - no cross-module store dependencies