Skip to content

feat: Vue 2 → Vue 3 migration with Composition API#307

Closed
AgustinRamiroDiaz wants to merge 9 commits intoSTS-Rosario:masterfrom
AgustinRamiroDiaz:feat/vue3-migration
Closed

feat: Vue 2 → Vue 3 migration with Composition API#307
AgustinRamiroDiaz wants to merge 9 commits intoSTS-Rosario:masterfrom
AgustinRamiroDiaz:feat/vue3-migration

Conversation

@AgustinRamiroDiaz
Copy link
Contributor

Summary

  • Complete Vue 2 → Vue 3 migration: Vue 3.5, Vue Router 4, Pinia (replaces Vuex 2), Vite (replaces Webpack 4), vue-i18n 11
  • All 73 components converted from Options API to Composition API with <script setup>
  • 16 Vuex modules → 16 Pinia stores using defineStore() with setup syntax
  • Library replacements: vue-strap → native HTML, vuejs-datepicker → @vuepic/vue-datepicker, vue2-leaflet → @vue-leaflet/vue-leaflet, event bus → mitt, filters → composable functions

Changes breakdown

Category Details
Build system Webpack 4 → Vite, removed .babelrc and build/ directory
Core framework Vue 3.5, Vue Router 4, Pinia 3
State management 16 Vuex modules → 16 Pinia stores (src/stores/)
Components 73 .vue files converted to <script setup> Composition API
Directives Updated lifecycle hooks (bind→beforeMount, inserted→mounted, etc.)
Plugins vue-i18n 8→11, replaced vue-strap, vue-head, vue-analytics, datepickers, leaflet
Environment process.env.*import.meta.env.VITE_* throughout
Template syntax Slots (slot="x"#x), .syncv-model:, removed .native, v-for key placement
New composables useFormatters.js (replaces filters), usePagination.js
Deleted Old Vuex store (src/store/), webpack configs (build/), .babelrc

Test plan

  • npx vite build passes (verified)
  • npm run dev — app starts without console errors
  • Login/register flow works
  • Trip creation (NewTrip) works
  • Trip detail with Leaflet map loads
  • Messaging/conversations work
  • Search and filtering work
  • Profile editing works
  • Admin pages load
  • Mobile/Capacitor build still works

🤖 Generated with Claude Code

@AgustinRamiroDiaz
Copy link
Contributor Author

@GonzaloGM I went ahead with this, and now I realize I might have been too hurried.
Is this something that you want? I like working on this, but I don't want to be a bother

@GonzaloGM
Copy link
Contributor

@AgustinRamiroDiaz Yes of course, I was actually going to tackle the upgrade this very weekend but you got to it first haha same with the Laravel upgrade. Thanks for your help!

@GonzaloGM
Copy link
Contributor

@AgustinRamiroDiaz The only thing is that there were a couple branches merged lately so that might cause quite a few conflicts :( we need to make sure we don't leave anything out when solving them.

@AgustinRamiroDiaz
Copy link
Contributor Author

@AgustinRamiroDiaz The only thing is that there were a couple branches merged lately so that might cause quite a few conflicts :( we need to make sure we don't leave anything out when solving them.

For sure! I'm rebasing constantly. I'll also be creating tons of tests

Do you think there will be more merges in these days?

@GonzaloGM
Copy link
Contributor

@AgustinRamiroDiaz I think not! I think unless a bug comes up we can hold adding more code until we finish this migration so we don't complicate things for this PR :)

AgustinRamiroDiaz and others added 2 commits February 21, 2026 12:54
- Vue 3.5 + Vite + Pinia (replaces Vue 2.6 + Webpack 4 + Vuex 2)
- All 73 components converted to Composition API with <script setup>
- Vue Router 4 with createWebHistory
- vue-i18n 9, bootstrap-vue-next, @vue-leaflet/vue-leaflet
- mitt event bus (replaces Vue instance event bus)
- Custom directives updated to Vue 3 lifecycle hooks
- Filters replaced with composable functions
- Docker updated to Node 18 for Vite compatibility
- Comprehensive Playwright e2e test suite (57 tests)
- Fix Leaflet: expose L as global for leaflet-routing-machine
- Fix Login.vue: call onLoggin() after successful authentication
- Convert upstream BannedUsersList.vue to Composition API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tore

- Rewrite e2e tests to use UI interactions instead of direct API calls
  for maximum UI coverage
- Fix DatePicker.vue: use @vuepic/vue-datepicker props (min-date/max-date)
  instead of old vuejs-datepicker disabled object that disabled the whole picker
- Fix conversations store: expose userList as 'users' to match component access
- Login helper clears localStorage between logins for multi-user test flows
- Filter expected Network Errors in JS error assertion test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AgustinRamiroDiaz and others added 3 commits February 21, 2026 21:35
- Convert IdentityValidation.vue and ManualIdentityValidation.vue from
  Vuex/Options API to Pinia/Composition API (<script setup>)
- Fix docker-compose.yml: remove undefined 'esnet' network reference
- Fix e2e helpers: login flow, dismissOnboarding strict mode, datepicker
  selectors updated from Vue 2 (.vdp-datepicker__) to Vue 3 (.dp__)
- Fix conversations test: use .modal-container (not .modal-content) for
  Carpoodatos modal, navigate via trip detail page instead of user search
- Add global-setup.js: reset test user state before runs (the backend
  bans users who create >4 trips in 24h, which accumulates across runs)
- Add qrcode dependency (used by ManualIdentityValidation)

All 58 Playwright tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix P0 critical issues: router.replace calling push, profileComplete guard
missing next(), double next() in route guards, social login crash, device
store Vuex-era params, startThread missing notificationsStore, $moment
registration, logout side effects, loadParams not exposed.

Fix P1 issues: Calendar.vue rewrite for vue-datepicker API, dateFormatter
directive, Modal transition CSS classes, circular i18n import extraction,
trip CRUD cross-store sync, profile references, changeProperty user sync.

Fix P2 issues: watch params swap, useI18n scope, password redirect, rates
reply sync, onboarding persistence, router-link tag/class fixes, null
checks in notifications/passenger stores, maps string replace, leaflet
CSS version, auth token replaceAll, deep clone for UpdateProfile.

Infrastructure: nginx.conf for SPA routing, Dockerfile npm ci, i18n module
extraction, eslint config cleanup, .dockerignore updates.

Add 14 new e2e test specs covering friends, logout, messages, notifications,
passenger cancel, ratings, auto-accept, trip edit/cancel/detail, view
profile, password reset, return trip, and subscriptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AgustinRamiroDiaz
Copy link
Contributor Author

@GonzaloGM I think most of the work is done. You can start reviewing if you'd like

I'll continue testing and seeing if I can find any bugs.

AgustinRamiroDiaz and others added 4 commits February 22, 2026 09:06
Remove 15 duplicate translation keys in src/language/i18n.js (no-dupe-keys).
Fix 3 quote style errors in Trip.vue and Trips.vue.
Downgrade pre-existing Vue 3 migration template warnings (v-for-key,
deprecated slot/router-link-tag, etc.) in .eslintrc.cjs so they don't
block CI while migration debt is addressed incrementally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set user0 as admin in global-setup.js and update admin.spec.js to
login as user0 for the admin page test, removing the test.skip() fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical fixes:
- Fix passenger store function signatures (makeRequest, accept, cancel)
  to resolve stores internally instead of expecting them as arguments
- Fix profile.setReply() reversed mutation direction
- Remove startThread race condition (redundant bus.on after startApp)
- Fix AdminManualIdentityValidationReview Vuex import and process.env
- Replace dual createApp() with setActivePinia()
- Add defineExpose to Tabset.vue for activateTab/getRememberedTab
- Clear all user-specific stores on logout to prevent data leakage
- Add missing bus.on('back-click') in transactions.vue

High-severity fixes:
- Add index guards for splice(-1,1) in removeCurrentTripPassengerById
- Fix router-link tag prop for Vue Router 4 in ProfileInfo.vue
- Fix Modal clickOutsideHandler ref issue with plain function
- Fix bus.on memory leaks (HeaderApp, Trips, NewTrip, ConversationChat)
- Prevent duplicate script injection (MercadoPago, reCAPTCHA)
- Fix window.addEventListener leak in Trips.vue
- Fix auth.searchUsers() returning undefined for non-admin
- Fix cordova.js router.push callback style for Vue Router 4
- Add null guards in cars, subscriptions, rates, notifications stores
- Fix router.push/replace/go for string args and splice logic
- Fix debounceInput singleton causing cross-instance conflicts
- Fix device.js global listeners stacking on HMR

Medium-severity fixes:
- Fix invalid moment timezone to America/Argentina/Buenos_Aires
- Fix ternary operator precedence in Trip.vue and TripDriver.vue
- Fix Tab.vue id never being assigned from registerTab
- Fix fancyCheckbox.js el.outerHTML breaking Vue DOM tracking
- Fix toast.js reading properties on string instead of options object
- Add null guards in Login.vue and ConversationList.vue
- Pin leaflet-routing-machine CDN version

Build & test improvements:
- Add process.env shim in vite.config.js
- Set page title in index.html
- Extract API_BASE in e2e helpers for configurability
- Add test retries and reduce workers to prevent state corruption

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Eliminates ~1.2s external fetch on page load by bundling Leaflet and
leaflet-routing-machine CSS locally via npm imports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AgustinRamiroDiaz
Copy link
Contributor Author

@GonzaloGM the PR continues to get bigger and bigger, and I'm less confident of the changes

WDYT about going with another approach like this one https://v3-migration.vuejs.org/migration-build.html?

We could tackle it with smaller, incremental changes instead of one huge PR

I can also help with that approach as well

@GonzaloGM
Copy link
Contributor

@AgustinRamiroDiaz Yeah it's massive PR which will very difficult to review to be honest. I think that other approach looks very interesting as we might get an initial PR to make it compile (with warnings) and we can make sure everything works, then merge it, and make separate smaller PRs when tackling individual warnings. Do you want to give it a try and see if getting to that initial successful build step makes for a manageable PR?

@AgustinRamiroDiaz
Copy link
Contributor Author

@AgustinRamiroDiaz Yeah it's massive PR which will very difficult to review to be honest. I think that other approach looks very interesting as we might get an initial PR to make it compile (with warnings) and we can make sure everything works, then merge it, and make separate smaller PRs when tackling individual warnings. Do you want to give it a try and see if getting to that initial successful build step makes for a manageable PR?

Yes! I'll be discarding this PR and trying out the new approach

@GonzaloGM
Copy link
Contributor

@AgustinRamiroDiaz sounds good, thanks for giving it a go! Migrations like this on a big app can be a real pain, especially when it's a moving target.

@AgustinRamiroDiaz
Copy link
Contributor Author

closing in favor of #314

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants