Modernize Vue 2 App to Vue 3 with TypeScript -- 3

Job ID: 39941266

Budget: €30 – €250 EUR

# Technical Task — Vue 3 Migration Rules (Bundles, Licenses, Transactions)

## 1) Goal
Unify migration of components to **Vue 3** with **Options API** and **TypeScript**, upgrade to **Bootstrap 5.3+**, **VeeValidate v4**, **vue‑i18n v9+**, replace **Vuex → Pinia**, remove **Inspinia**, and align layout/UX with the standards used in **ProductForm / ProductCreatePage / ProductEditPage**.

The candidates will be granted access to the private GitHub repository and will be able to see the current state of these components.

## 2) Tech Stack and Versions
- Vue 3.x (Options API).
- TypeScript 5.x (strict=true).
- Pinia 2.x.
- VeeValidate 4.x (component API).
- vue-i18n 9.x (Composition API only for `t`).
- Vue Router 4.x.
- Bootstrap 5.3.x.
- **bootstrap-vue-next** with auto-import via **BootstrapVueNextResolver** → **do not** import components manually and **do not** register them in `components`.
- **head** (unhead.unjs.io) instead of the old `meta` library.

## 3) Code Style and Options API
- Use **Options API** (`data`, `props`, `computed`, `methods`, `watch`).
- `setup()` is allowed **only** to get `t` from `useI18n()` and to access Pinia stores; do not place business logic in `setup()`.
```ts
setup() {
const { t } = useI18n();
return { t };
}
```
- Always declare the component `name`.

## 4) TypeScript
- All `.vue` files must use `<script lang="ts">`.
- Explicitly type `props`, `emits`, `data()` (via interface), `computed`, `methods`, and form events.
- **Do not define local (inline) types** inside components → import types from **`/types/*`**.
- **Do not duplicate types** that exist in **`netlicensing-client`** — import them from that library.

## 5) Bootstrap 4 → 5.3+ (required renames)
- `.left-*` → `.start-*`, `.right-*` → `.end-*`.
- `.float-left` → `.float-start`, `.float-right` → `.float-end`.
- `.border-left` → `.border-start`, `.border-right` → `.border-end`.
- `.rounded-left` → `.rounded-start`, `.rounded-right` → `.rounded-end`.
- `.ml-*` → `.ms-*`, `.mr-*` → `.me-*`.
- `.pl-*` → `.ps-*`, `.pr-*` → `.pe-*`.
- `.text-left` → `.text-start`, `.text-right` → `.text-end`.

**Additionally (apply in all places):**
- Replace `.form-group` with Bootstrap spacing classes (e.g., `.mb-3`). Do not create custom group wrappers.
- `custom-select` → `form-select`.
- `input-group-append` / `input-group-prepend` → not used in BS5.
- `badge-pill` → `badge` + `rounded-pill`.
- Use **Bootstrap Icons** (migrate away from Font Awesome).
- **Classes with `nlic` prefix must be replaced with Bootstrap defaults**: `btn-nlic` → `btn-primary`, `text-nlic` → `text-primary`, etc.
- **Do not use jQuery**; remove/replace any jQuery dependencies.
- **Do not use `b-tooltip` / `VBTooltip`**; use the standard HTML `title` attribute for tooltips.

## 6) Styles and Inspinia
- **Do not change global styles.** The legacy `/assets` folder is **not** migrated because it depends on Inspinia.
- Remove all Inspinia-specific classes/styles.
- Use only clean Bootstrap 5 and existing project components. Do not add custom CSS unless explicitly approved.

## 7) Navigation and Headers
- Use the existing **`PageHeader.vue`** for page title, breadcrumbs, and action buttons.
- For other UI needs prefer **bootstrap-vue-next** components (e.g., `BButtonGroup` with `append`/`prepend` slots).

## 8) Pinia (replacing Vuex)
- Access store state/actions using **`mapState` / `mapActions`** in **Options API**.
- Do **not** use `storeToRefs()`.

## 9) VeeValidate v4 (component API)
- Use `<VForm>`, `<VField>`, `<ErrorMessage>`.
- Define validation via the `rules` prop on `<VField>` (no schema).
- Each field must have a `name`; bind `<ErrorMessage>` via `name`.
- Handle submit via `VForm` (`@submit` or `@submit.prevent`) with async logic.

## 10) Translations (vue‑i18n v9+)
- Get translations only via `const { t } = useI18n()` in `setup()` and expose `t` to the template.
- **No HTML** inside translation keys. For embedded HTML use `<i18n-t>`.
- Follow existing key casing (kebab-case or dot.case) used in project locales.

## 11) Layout and Responsiveness
- Use Bootstrap 5 grid and spacing utilities.
- Validate layouts for `sm / md / lg` breakpoints.

## 12) Loading and Buttons
- Buttons must be **`BButton`** and use the `loading` prop where applicable.
- For page-level loading use **`TheLoader.vue`** with a `loading` prop and `loading` slot.
- In the `loading` slot render a **Bootstrap 5 skeleton**. You may use **`SkeletonTable.vue`** or **`TheSkeleton.vue`** components.
- See examples in **`ProductsList.vue`** and **`ProductForm.vue`**.

## 13) API Calls
- Use existing service classes/methods; **do not** introduce new endpoints.
- Handle errors with `try/catch`. Do not leave `console.log` statements in production builds.

## 14) File Structure
- Pages: `src/pages/...Page.vue`.
- Forms/lists: `src/components/...`.
- Types: `src/types/...`.
- Locales: existing `src/locales/...` structure.

## 15) Prohibitions
- No Composition API for business logic.
- No jQuery. No Inspinia.
- Do not modify store/service architecture.
- Do not add new dependencies without approval.

## 16) Pre‑delivery Checklist
1. Vue 3 (Options API) + TS — build passes with no type errors.
2. Bootstrap 5 class renames applied as per §5.
3. VeeValidate v4 used with `<VForm>/<VField>/<ErrorMessage>` and `rules` on fields.
4. vue‑i18n v9 used via `useI18n()`; no HTML in keys; `<i18n-t>` where needed.
5. Pinia access via `mapState`/`mapActions` (Options API).
6. No Inspinia classes; legacy `/assets` not migrated.
7. Buttons use `BButton[loading]`; page loader uses `TheLoader.vue` with skeleton.
8. Layout responsive at sm/md/lg breakpoints.

---

## 17) Component‑Specific Requirements

### 17.1) Bundles
**BundlesPage.vue** and **BundlesList.vue**
- Update **by following** `ProductsPage.vue` and `ProductsList.vue` as reference.
- ~95% identical: only the **`GET` endpoint** and entity naming differ.
- Mirror template structure, pagination/filters/loading behavior, action buttons, usage of `PageHeader.vue`, `TheLoader.vue`, and `BButton` with `loading`.

**BundleForm.vue**
- After the client library update, `licenseTemplateNumbers` is now an **array of strings** (previously a comma‑separated string). Update types, bindings, validation, and API (de)serialization accordingly.
- **Use multi‑`v-model`** instead of deprecated model methods (`forget`, `reset`, `sync`) when passing fields to child components.
- **Do not** use:
```vue
<General ref="general"
:bundle="bundleModel"
@input="bundleModel.set($event)"
@reset="bundleModel.reset($event)"
@forget="bundleModel.forget($event)"
@error="$emit('error', $event)"/>
```
- **Use:**
```vue
<General
ref="general"
v-model:active="bundleModel.active"
v-model:name="bundleModel.name"
v-model:number="bundleModel.number"
/>
```

### 17.2) Licenses
**LicensesPage.vue** and **LicensesList.vue**
- Update **by following** `CustomersPage.vue` and `CustomersList.vue` as reference.
- Visual structure and behavior are almost identical; change only the **`GET` endpoint** and entity naming.
- Mirror template structure, pagination/filters/loading behavior, `PageHeader.vue`, `TheLoader.vue`, `BButton[loading]` usage.

**LicenseForm.vue**
- **Use multi‑`v-model`** bindings for passing fields to child components (same approach as in `BundleForm.vue`).
- Do **not** use deprecated model methods (`forget`, `reset`, `sync`).

Start your proposal with #IGOTIT hashtag to confirm you've read this description in full.

== Deliverables ==

- Fully migrated and modernized components stated in this description
- All components must pass linting and unit tests and be fully compilable and functional
- GitHub pull request with clear commit history
- Only accepted PR changes will be merged
- The payment will be released upon successful review and merge of the PR!!