{"id":47870091,"url":"https://github.com/cdmain/loan-eligibility-simulator","last_synced_at":"2026-04-04T00:47:35.991Z","repository":{"id":341353608,"uuid":"1169802860","full_name":"cdmain/loan-eligibility-simulator","owner":"cdmain","description":"Loan Eligibility Simulator — Vue 3.5 + TypeScript + Module Federation + TanStack + Tailwind CSS 4","archived":false,"fork":false,"pushed_at":"2026-03-01T12:58:58.000Z","size":103,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-04T00:47:33.133Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://cdmain.github.io/loan-eligibility-simulator/","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cdmain.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-01T08:32:27.000Z","updated_at":"2026-03-01T12:59:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cdmain/loan-eligibility-simulator","commit_stats":null,"previous_names":["cdmain/loan-eligibility-simulator"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cdmain/loan-eligibility-simulator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdmain%2Floan-eligibility-simulator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdmain%2Floan-eligibility-simulator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdmain%2Floan-eligibility-simulator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdmain%2Floan-eligibility-simulator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdmain","download_url":"https://codeload.github.com/cdmain/loan-eligibility-simulator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdmain%2Floan-eligibility-simulator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31383635,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T23:20:52.058Z","status":"ssl_error","status_checked_at":"2026-04-03T23:20:51.675Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-04T00:47:34.760Z","updated_at":"2026-04-04T00:47:35.972Z","avatar_url":"https://github.com/cdmain.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Loan Eligibility Simulator\n\nA responsive micro-frontend application where users input their income, expenses, and desired loan amount to see estimated eligibility results (mocked data).\n\nBuilt with **Vue 3.5**, **TypeScript** (strict mode), **Tailwind CSS 4**, **Rsbuild**, **Module Federation**, **TanStack Form/Query**, **Reka UI**, and **Zod** validation.\n\n---\n\n## Quick Start\n\n```bash\n# Install dependencies\npnpm install\n\n# Start the simulator (standalone) — http://localhost:3001\npnpm dev:simulator\n\n# Or start both shell + simulator (MFE mode)\npnpm dev\n# → Shell:     http://localhost:3000\n# → Simulator: http://localhost:3001\n```\n\n## Docker (one command)\n\n```bash\n# Build and run with Docker / Rancher Desktop\ndocker compose up --build\n\n# → http://localhost:3000\n```\n\nOr without Compose:\n\n```bash\ndocker build -t loan-simulator .\ndocker run -p 3000:80 loan-simulator\n```\n\n---\n\n## Architecture\n\n```\n├── apps/\n│   ├── simulator/      # Remote module — the Loan Eligibility Simulator\n│   │   ├── src/\n│   │   │   ├── components/     # UI + feature components\n│   │   │   ├── composables/    # useLoanCalculation, useEligibility\n│   │   │   ├── schemas/        # Zod validation schemas\n│   │   │   ├── types/          # TypeScript types\n│   │   │   ├── mocks/          # Mock eligibility API\n│   │   │   ├── lib/            # Utilities (cn, currency formatting)\n│   │   │   ├── styles/         # Tailwind CSS theme tokens\n│   │   │   ├── App.vue         # Page orchestrator\n│   │   │   ├── entry.ts        # Module Federation export\n│   │   │   └── main.ts         # Standalone bootstrap\n│   │   └── rsbuild.config.ts\n│   └── shell/          # Host — consumes the simulator via MF\n│       └── rsbuild.config.ts\n├── Dockerfile          # Multi-stage build → nginx\n├── docker-compose.yml\n└── eslint.config.mjs   # ESLint Stylistic (no Prettier)\n```\n\n### Module Federation\n\nThe project demonstrates a **micro-frontend architecture**:\n\n| App | Role | Port | What it does |\n|---|---|---|---|\n| `simulator` | Remote | 3001 | Exposes `./app` — the loan simulator component |\n| `shell` | Host | 3000 | Consumes the remote and renders it inside a shell layout |\n\nThe simulator also works **standalone** — it mounts its own Vue app when accessed directly.\n\n---\n\n## Tech Stack\n\n| Concern | Tool |\n|---|---|\n| Framework | Vue 3.5 (Composition API, `\u003cscript setup\u003e`) |\n| Language | TypeScript 5 (strict mode) |\n| Bundler | Rsbuild (Rspack) |\n| Micro-frontends | Module Federation via `@module-federation/rsbuild-plugin` |\n| Styling | Tailwind CSS 4 + PostCSS |\n| Primitives | Reka UI |\n| Component patterns | shadcn-vue (CVA + Tailwind Merge) |\n| Forms | TanStack Vue Form |\n| Data fetching | TanStack Vue Query (mutation for mock API) |\n| Validation | Zod |\n| Utilities | VueUse |\n| Linting | ESLint + @stylistic (no Prettier) |\n| Icons | Lucide Vue Next |\n| Container | Docker (multi-stage nginx) |\n\n---\n\n## Scripts\n\n| Command | Description |\n|---|---|\n| `pnpm dev` | Start both shell and simulator in development mode |\n| `pnpm dev:simulator` | Start only the simulator |\n| `pnpm dev:shell` | Start only the shell |\n| `pnpm build` | Production build for all apps |\n| `pnpm lint` | Run ESLint across all apps |\n| `pnpm type-check` | Run TypeScript type checking |\n\n---\n\n## How It Works\n\n1. **Input**: The user enters monthly gross income, itemised expenses, desired loan amount, and repayment term.\n2. **Real-time preview**: As inputs change, computed values (estimated rate, DTI ratio, affordability gauge) update live.\n3. **Eligibility check**: On form submission, a mock async API evaluates eligibility using:\n   - **Debt-to-income ratio** (DTI) — fails at \u003e42%, conditional at 35–42%\n   - **Credit score** (simulated 300–850 range)\n   - **Disposable income** after repayments\n   - **Maximum affordable amount** (capped at 30% of disposable income)\n4. **Results**: A detailed breakdown including status badge, affordability gauge, repayment schedule, interest rate, and assessment notes.\n\n### Validation\n\nAll form inputs are validated at the field level using **Zod** schemas through the **TanStack Zod Form Adapter**:\n\n- Income: min R 1 000\n- Expenses: non-negative, upper bounds\n- Loan amount: R 5 000 – R 10 000 000\n- Term: 6 – 360 months\n- Cross-field: total expenses must be less than income\n\n---\n\n## Design Decisions\n\n- **Presentational components** — components receive props and emit events; the page (`App.vue`) orchestrates state and side effects.\n- **Semantic colour tokens** — all colours reference CSS custom properties that switch between light and dark mode automatically. No hardcoded hex values in components.\n- **Tailwind CSS 4** — uses `@theme inline` and `@custom-variant dark` for runtime theme switching without a rebuild.\n- **CVA (class-variance-authority)** — component variants (Button, Badge) are type-safe and composable.\n- **No Prettier** — formatting is handled by ESLint Stylistic rules.\n- **Module Federation bootstrap pattern** — `main.ts` dynamically imports `bootstrap.ts` so shared dependencies (Vue) are resolved before mounting.\n\n---\n\n## Building \u0026 Testing\n\n```bash\n# Type check\npnpm type-check\n\n# Lint\npnpm lint\n\n# Production build\npnpm build\n\n# Docker\ndocker compose up --build\n# Open http://localhost:3000\n```\n\n---\n\n## License\n\nThis project was built as a technical assessment and is provided as-is.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdmain%2Floan-eligibility-simulator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdmain%2Floan-eligibility-simulator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdmain%2Floan-eligibility-simulator/lists"}