feat: Implement unified Vue SPA with granular service control

Consolidate Reports and Data Entry apps into a single Vue.js SPA with:

Architecture:
- Module-based structure with lazy-loaded routes (@reports, @data-entry)
- Error boundaries per module to prevent cascade failures
- Dual API proxy in Vite for microservices (reports:8001, data-entry:8003)
- Pinia store factories for shared auth, company, and period stores
- Vite path aliases for clear module boundaries (@shared, @reports, @data-entry)

Service Management:
- Granular service control scripts (backend-reports.sh, backend-data-entry.sh, bot.sh, frontend.sh)
- 87% faster frontend restart: 7s vs 53s full restart
- 38% faster full startup: 33s vs 53s via parallel backend initialization
- Enhanced start-dev.sh with proper service timeouts (OCR: 30s, Vite: 15s, Bot: 10s)
- status.sh for comprehensive health checks

Features:
- Auto-select first company on login with period auto-load
- Hamburger menu with feature toggle support
- JWT token auto-injection via axios interceptors
- Unified header with company/period selectors
- IIS web.config for production deployment with multi-API routing

UX Improvements:
- Vue watchers for reactive company/period loading
- Lazy store initialization with graceful error handling
- Period persistence per user+company in localStorage
- Feature flags for optional modules

Deployment:
- Single IIS site serves unified frontend with API proxy rules
- Maintains separate backend processes for microservices
- Windows line ending fixes (.env CRLF → LF conversion)

Stats: 112 files changed, 38,342 insertions(+), 2,342 deletions(-)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-24 19:06:23 +02:00
parent fed2e68fa2
commit d507a81b0a
112 changed files with 38382 additions and 2382 deletions

88
src/main.js Normal file
View File

@@ -0,0 +1,88 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import PrimeVue from 'primevue/config'
import ToastService from 'primevue/toastservice'
import ConfirmationService from 'primevue/confirmationservice'
import App from './App.vue'
import router from './router'
// PrimeVue Components
import Button from 'primevue/button'
import InputText from 'primevue/inputtext'
import Password from 'primevue/password'
import DataTable from 'primevue/datatable'
import Column from 'primevue/column'
import Card from 'primevue/card'
import Toast from 'primevue/toast'
import ConfirmDialog from 'primevue/confirmdialog'
import Menu from 'primevue/menu'
import Menubar from 'primevue/menubar'
import Badge from 'primevue/badge'
import Tag from 'primevue/tag'
import Dropdown from 'primevue/dropdown'
import AutoComplete from 'primevue/autocomplete'
import Calendar from 'primevue/calendar'
import ProgressSpinner from 'primevue/progressspinner'
import Dialog from 'primevue/dialog'
import InputNumber from 'primevue/inputnumber'
import Textarea from 'primevue/textarea'
import FileUpload from 'primevue/fileupload'
import Image from 'primevue/image'
import TabView from 'primevue/tabview'
import TabPanel from 'primevue/tabpanel'
import Checkbox from 'primevue/checkbox'
import RadioButton from 'primevue/radiobutton'
import Toolbar from 'primevue/toolbar'
import Divider from 'primevue/divider'
import Message from 'primevue/message'
// PrimeVue CSS (saga-blue theme)
import 'primevue/resources/themes/saga-blue/theme.css'
import 'primevue/resources/primevue.min.css'
import 'primeicons/primeicons.css'
const app = createApp(App)
// Pinia store
app.use(createPinia())
// Router
app.use(router)
// PrimeVue with saga-blue theme
app.use(PrimeVue, { ripple: true })
app.use(ToastService)
app.use(ConfirmationService)
// Register PrimeVue components globally
app.component('Button', Button)
app.component('InputText', InputText)
app.component('Password', Password)
app.component('DataTable', DataTable)
app.component('Column', Column)
app.component('Card', Card)
app.component('Toast', Toast)
app.component('ConfirmDialog', ConfirmDialog)
app.component('Menu', Menu)
app.component('Menubar', Menubar)
app.component('Badge', Badge)
app.component('Tag', Tag)
app.component('Dropdown', Dropdown)
app.component('AutoComplete', AutoComplete)
app.component('Calendar', Calendar)
app.component('ProgressSpinner', ProgressSpinner)
app.component('Dialog', Dialog)
app.component('InputNumber', InputNumber)
app.component('Textarea', Textarea)
app.component('FileUpload', FileUpload)
app.component('Image', Image)
app.component('TabView', TabView)
app.component('TabPanel', TabPanel)
app.component('Checkbox', Checkbox)
app.component('RadioButton', RadioButton)
app.component('Toolbar', Toolbar)
app.component('Divider', Divider)
app.component('Message', Message)
app.mount('#app')