Skip to content

VitalinkOrg/VitalinkFrontend

Repository files navigation

Vitalink Frontend

Nuxt 3 Vue 3 TypeScript Bootstrap Netlify

A multi-role healthcare web platform that connects patients with doctors and clinics, facilitates appointment booking, and integrates a credit-based payment system backed by finance entities and insurance companies.


Table of Contents


High-level Description

Vitalink is a B2C2B healthcare marketplace built on Nuxt 3. It solves the fragmented experience of booking medical appointments by bringing together four distinct actor types onto a single platform:

Role Path prefix Description
Patient (CUSTOMER) /pacientes Browse doctors, book appointments, manage credits & payments
Doctor / Clinic (LEGAL_REPRESENTATIVE) /medicos Manage availability, services, patient queue, and earnings
Finance Entity (FINANCE_ENTITY) /socio-financiero Administer credit lines, suppliers, and financial configuration

The application is a frontend-only SPA/SSR that communicates exclusively with an external REST API. There is no backend code in this repository.


Tech Stack

Core

Technology Version Role
Nuxt 3 ^3.8.2 Meta-framework (SSR + SPA, routing, server middleware)
Vue 3 ^3.3.12 UI component model (Composition API)
TypeScript via Nuxt Static typing throughout pages, components, and composables
Vue Router 4 ^4.2.5 File-system routing (auto-generated by Nuxt)

Styling

Technology Version Role
Bootstrap 5 ^5.3.3 Responsive grid, utility classes, components
Sass ^1.69.6 SCSS preprocessing, variables, mixins, and global tokens
@popperjs/core ^2.11.8 Tooltip and dropdown positioning for Bootstrap JS

Data Fetching & HTTP

Technology Version Role
$fetch (Nuxt built-in) Primary HTTP client for all API calls
Axios ^1.6.5 Secondary client for specific request flows

UI Components & Utilities

Technology Version Role
VueUse ^10.9.0 Composable utilities (debounce, event listeners, storage)
nuxt-icon ^0.6.8 Icon rendering from Iconify registry
@vuepic/vue-datepicker ^11.0.2 Date & time picker for appointment scheduling
v-calendar ^3.1.2 Full calendar display for availability management
Chart.js + vue-chartjs ^4.4.7 / ^5.3.2 Dashboard analytics and doughnut charts

Payments & Documents

Technology Version Role
Cybersource via API Payment gateway for appointment billing
jsPDF + jspdf-autotable ^3.0.1 / ^5.0.2 Client-side PDF generation for receipts and reports
jwt-decode ^4.0.0 Decoding JWT access tokens for role extraction

Developer Tooling

Technology Role
Nuxt DevTools In-browser debugging panel
Prettier ^3.4.2 Code formatting
ESLint Static analysis (see .eslintrc.json)

Architecture & Design Patterns

Overall Structure

The application follows a feature-domain layered architecture on top of Nuxt 3's file-system conventions:

Routing layer    →  pages/          (Nuxt auto-routes; one file = one route)
View layer       →  components/     (reusable UI, split by domain and atomic level)
Business logic   →  composables/    (all state, side effects, and API calls live here)
HTTP layer       →  composables/api/  (one composable per API resource)
Type system      →  types/          (shared TypeScript interfaces used everywhere)
Middleware       →  middleware/      (route guards enforcing role-based access)

Component Organization — Hybrid Atomic + Feature-Based

components/
├── atoms/          # Stateless, primitive UI pieces (icons, badges)
├── ui/             # Reusable cross-domain widgets (date picker, toast, table base)
├── website/        # Public-facing marketing and search pages
├── pacientes/      # Patient-dashboard feature components
├── medicos/        # Doctor/clinic-dashboard feature components
└── aseguradoras/   # Insurance company workflow components

State Management — Composables (no Pinia / Vuex)

All shared state is managed through reactive composables using useState (Nuxt's SSR-safe wrapper over ref):

  • useAuthToken() — JWT lifecycle: read, store, clear.
  • useAuthState() — Logged-in user's decoded profile.
  • useUserInfo() — Cached user data (patient or supplier record).
  • useModalManager() / useMedicalModalManager() — Global modal open/close state.
  • useToast() — Notification queue.

Authentication & Authorization

  • Mechanism: Custom JWT flow — no third-party auth library.
  • Storage: Access token stored as a cookie (role key). Expiry is checked client-side via payload.exp * 1000 < Date.now().
  • Token refresh: Handled by useRefreshToken() composable, which intercepts 401 responses.
  • Route guards: Five Nuxt middleware files enforce role access before navigation:
    • authPacientesCUSTOMER
    • authDoctorsHospitalsLEGAL_REPRESENTATIVE
    • authInsurances → insurance role
    • authHospitals → hospital sub-role
    • authLogin → redirects authenticated users away from login pages

API Layer

A single generic wrapper (useApi.ts) wraps $fetch and:

  1. Injects the Authorization: Bearer <token> header.
  2. Catches errors and maps codes to Spanish user-facing messages via translateError().
  3. Returns a typed IUsableAPI<T> object.

Each resource has its own composable (e.g. useAppointment, useSupplier, usePayment) that delegates to useApi.


Key Features

  • Multi-role SPA — Four independent dashboards served from a single Nuxt application, each gated by JWT role claims.
  • Appointment booking flow — Step-by-step stepper (reservar-cita-valoracion) covering doctor search, specialty selection, date/time picking, and confirmation.
  • Credit-based payment system — Patients can request appointment credit; insurance companies approve/reject through a dedicated workflow; finance entities administer credit lines.
  • Cybersource payment integration — Secure payment processing with a dedicated SPA receipt page (/receipt-spa) for post-payment callbacks.
  • Availability management — Doctors configure weekly availability slots via useAvailability and the availability-selector component.
  • Client-side PDF generation — Appointment reports and receipts generated in the browser using jsPDF + AutoTable, with no server round-trip.
  • Dashboard analytics — Chart.js-powered doughnut charts and data summaries via useDashboardCharts and vue-chartjs.
  • Doctor public profiles — Dynamic routes (/perfiles/doctor/[doctor], /perfiles/hospital/[hospital]) with reviews, gallery, specialties, packages, and services.
  • Centralized Spanish error translation — All API error codes are mapped to human-readable Spanish messages in utils/errorTranslations.ts.
  • Responsive Bootstrap 5 UI — Grid, utility classes, and custom SCSS variables/mixins for brand theming.

Getting Started

Prerequisites

Requirement Version
Node.js >= 18.x (LTS recommended)
npm >= 9.x
Git any recent version

The project uses ES Modules ("type": "module" in package.json). Ensure your Node version supports native ESM.

Installation

1. Clone the repository

git clone https://github.com/VitalinkOrg/VitalinkFrontend.git
cd VitalinkFrontend

2. Install dependencies

npm install

The postinstall script runs nuxt prepare automatically, generating the .nuxt/ directory with TypeScript augmentations and auto-imports.

3. Configure environment variables

cp .env.example .env   # or create .env manually — see section below

4. Start the development server

npm run dev

The app will be available at http://localhost:3000.


Environment Variables

Create a .env file at the project root with the following keys:

# Base URL of the backend REST API
API_BASE_URL=

# Full URL Cybersource will redirect to after a payment transaction
NUXT_PUBLIC_CYBERSOURCE_RETURN_URL=

# Public base URL of this frontend application (used for redirects and links)
NUXT_PUBLIC_BASE_URL=

API_BASE_URL is exposed to the client via Nuxt's runtimeConfig.public. All keys prefixed with NUXT_PUBLIC_ are also client-accessible at runtime. Never store secrets in these variables.


Available Scripts

Script Command Description
Development npm run dev Starts the Nuxt dev server with HMR at localhost:3000
Build npm run build Compiles and optimizes the application for production (outputs to .output/)
Preview npm run preview Serves the production build locally for pre-deploy verification
Static Generate npm run generate Pre-renders all routes to static HTML files
Prepare npm run postinstall Runs nuxt prepare — regenerates .nuxt/ type declarations (run after npm install)

Folder Structure

VitalinkFrontend/
│
├── assets/                     # Static assets processed by the build pipeline
│   ├── main.scss               # Global SCSS entry point
│   ├── scss/                   # Shared variables, mixins, and global tokens
│   │   ├── _custom-variables.scss
│   │   ├── _globals.scss       # Auto-injected into every component via vite config
│   │   └── _mixin.scss
│   └── styles/
│       └── bootstrap/          # Selective Bootstrap SCSS imports
│
├── components/                 # 195 Vue SFCs, organized by domain
│   ├── atoms/                  # Primitive, stateless components (icons, badges)
│   ├── ui/                     # Cross-domain reusable widgets
│   ├── website/                # Public site components (search, booking, profiles)
│   ├── pacientes/              # Patient dashboard components
│   ├── medicos/                # Doctor/clinic dashboard components
│   └── aseguradoras/           # Insurance workflow components
│
├── composables/                # All business logic and shared state
│   ├── api/                    # One composable per API resource (16 files)
│   │   ├── useApi.ts           # Generic $fetch wrapper with auth + error handling
│   │   ├── useAuth.ts          # Login, register, token refresh, logout
│   │   ├── useAppointment.ts
│   │   ├── usePayment.ts       # Cybersource payment flow
│   │   └── ...
│   ├── useAuthToken.ts         # JWT read/write/clear from cookie
│   ├── useAuthState.ts         # Decoded user profile (reactive)
│   ├── useModalManager.ts
│   ├── useToast.ts
│   └── ...                     # 34 additional logic composables
│
├── layouts/                    # 16 role-specific and shared layout wrappers
│   ├── web.vue                 # Public website layout
│   ├── pacientes-dashboard.vue
│   ├── medicos-dashboard.vue
│   ├── aseguradoras-dashboard.vue
│   └── ...
│
├── middleware/                 # Nuxt route guards (run before page render)
│   ├── authPacientes.ts        # CUSTOMER role guard
│   ├── authDoctorsHospitals.ts # LEGAL_REPRESENTATIVE role guard
│   ├── authInsurances.ts       # Insurance role guard
│   ├── authHospitals.ts        # Hospital sub-role guard
│   └── authLogin.ts            # Redirect authenticated users away from login
│
├── pages/                      # File-system routes (43+ pages across 5 domains)
│   ├── index.vue               # Public homepage
│   ├── buscar.vue              # Doctor/clinic search
│   ├── receipt-spa.vue         # Cybersource post-payment receipt SPA
│   ├── auth/                   # Shared auth pages (login, password reset)
│   ├── pacientes/              # Patient dashboard pages
│   ├── medicos/                # Doctor dashboard pages
│   ├── socio-financiero/       # Finance entity dashboard pages
│   ├── clinicas/               # Clinic onboarding pages
│   ├── perfiles/               # Public doctor & hospital profile pages
│   └── admin/                  # Admin login & dashboard
│
├── public/                     # Assets served as-is (no processing)
│   ├── bootstrap.bundle.min.js # Bootstrap JS bundle (injected in <body>)
│   └── favicon.ico
│
├── src/                        # 130+ image assets (SVG/PNG illustrations)
│
├── types/                      # Shared TypeScript interfaces
│   ├── index.d.ts              # 760+ lines — all API entity interfaces
│   ├── auth.ts                 # UserRole enum, token types, role-route map
│   └── payment.ts              # Cybersource payment types and error class
│
├── utils/                      # Pure utility functions
│   ├── errorTranslations.ts    # API error code → Spanish message map
│   └── jwt.ts                  # Manual JWT base64 decode helper
│
├── app.vue                     # Root Vue component (NuxtLayout + NuxtPage)
├── nuxt.config.ts              # Nuxt configuration (modules, CSS, runtimeConfig)
├── tsconfig.json               # Extends .nuxt/tsconfig.json (auto-generated)
├── package.json
└── .env                        # Local environment variables (not committed)

Contribution Guidelines

Branch Strategy

main                  ← production-ready code; protected branch
├── feat/<topic>      ← new features or significant additions
├── fix/<topic>       ← bug fixes targeted at a specific area
├── refactor/<topic>  ← code improvements with no behavior change
└── docs/<topic>      ← documentation-only changes

Pull Request Flow

  1. Branch from main using the naming convention above.
  2. Keep PRs focused — one logical change per PR.
  3. Write a clear description explaining what changed and why.
  4. Verify the app builds without errors: npm run build.
  5. Manually test your change across all affected user roles (patient, doctor, insurance, finance).
  6. Request at least one reviewer before merging.
  7. Squash or rebase before merge to keep history linear.

Coding Standards

Area Convention
Language TypeScript everywhere — avoid untyped any
Components Vue 3 Composition API with <script setup lang="ts">
Composables One responsibility per composable; always prefix with use
Naming PascalCase for components; camelCase for composables, utils, and variables
Styling Bootstrap utility classes first; custom SCSS only for brand-specific overrides
API calls Always go through useApi() — never call $fetch directly from components
Error messages User-facing strings must be in Spanish; use translateError() from utils/errorTranslations.ts
Types Add new entity interfaces to types/index.d.ts; payment types to types/payment.ts
Formatting Run Prettier before committing — config is in package.json

Commit Message Format

<type>(<scope>): <short summary>

Types : feat | fix | refactor | docs | style | chore
Scopes: pacientes | medicos | aseguradoras | socio-financiero | website | auth | payments | ui

Examples:

feat(pacientes): add credit request status badge to citas table
fix(payments): handle Cybersource timeout error with Spanish message
refactor(ui): extract reusable pagination component from medicos table

License

This project is proprietary. All rights reserved by Vitalink. Unauthorized copying, distribution, or modification of this software, via any medium, is strictly prohibited without explicit written permission from the project owners.


Note for new contributors: There is currently no automated test suite — manual QA across all four user roles is required before merging any change that touches shared composables, middleware, or the API layer. Contributions adding Vitest unit tests or Playwright E2E tests are especially welcome.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors