FitTrack — Resultado: Capturas a Vue 3 + Vant

ui-to-vue-converter@1.0.2 · 3 módulos · 9 capturas procesadas

Vue 3 Vant 4 Vite Composition API
$ npx ui-to-vue-converter@1.0.2 --input ./screenshots --ui vant --output ./src
9
capturas procesadas
3
páginas (views/)
3
componentes shared
1
router generado
Vista previa de UI generada
9:41 ●●●
Buenos días,
María 👋
4
semana
2.4k
kcal
87%
racha
Hoy
🏋️
Push Day A
8 ejercicios · 45 min
Iniciar
🏃
Cardio 5K
1 ejercicio · 30 min
Hecho
🏠Inicio
📅Planes
📊Stats
👤Perfil
Archivos generados en src/
views/HomePage.vue156 líneas
views/WorkoutDetail.vue203 líneas
views/ProfilePage.vue128 líneas
components/WorkoutCard.vue72 líneas
components/StatBadge.vue45 líneas
components/TabBar.vue58 líneas
router/index.js38 líneas
Código generado — views/HomePage.vue
script
template
style
// views/HomePage.vue — generado por ui-to-vue-converter
<script setup>
import { ref, computed, onMounted } from 'vue'
import { showToast } from 'vant'
import WorkoutCard from '@/components/WorkoutCard.vue'
import StatBadge from '@/components/StatBadge.vue'
import TabBar from '@/components/TabBar.vue'
import { useRouter } from 'vue-router'

const router = useRouter()

// --- estado del dashboard ---
const user = ref({ name: 'María', avatar: '/assets/avatar-placeholder.png' })
const weeklyStats = ref({
  sessionsThisWeek: 4,
  caloriesBurned: 2400,
  streakPct: 87
})
const todayWorkouts = ref([])
const loading = ref(false)

// --- lógica ---
const greeting = computed(() => {
  const h = new Date().getHours()
  if (h < 12) return 'Buenos días'
  if (h < 18) return 'Buenas tardes'
  return 'Buenas noches'
})

onMounted(async () => {
  loading.value = true
  try {
    // TODO: reemplazar con llamada real a la API
    const res = await fetch('/api/workouts/today')
    todayWorkouts.value = await res.json()
  } catch {
    showToast('Error cargando los entrenos de hoy')
  } finally {
    loading.value = false
  }
})

function startWorkout(id) {
  router.push({ name: 'WorkoutDetail', params: { id } })
}
</script>
Componente compartido — WorkoutCard.vue
WorkoutCard.vue
<script setup>
// Extraído como shared porque aparece en HomePage y WorkoutDetail
const props = defineProps({
  workout: { type: Object, required: true }
})
const emit = defineEmits(['start'])

const statusColor = { done: '#22c55e', pending: '#6c63ff', skipped: '#ef4444' }
</script>

<template>
  <van-cell
    :title="workout.name"
    :label="workout.meta"
    is-link
    @click="emit('start')"
  >
    <template #icon>
      <div class="workout-icon">{{ workout.emoji }}</div>
    </template>
    <template #right-icon>
      <van-tag
        :color="statusColor[workout.status]"
        round
      >
        {{ workout.status === 'done' ? 'Hecho' : 'Iniciar' }}
      </van-tag>
    </template>
  </van-cell>
</template>
Router — router/index.js
router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    name: 'HomePage',
    component: () => import('@/views/HomePage.vue')
  },
  {
    path: '/workout/:id',
    name: 'WorkoutDetail',
    component: () => import('@/views/WorkoutDetail.vue'),
    props: true
  },
  {
    path: '/profile',
    name: 'ProfilePage',
    component: () => import('@/views/ProfilePage.vue')
  }
]

export default createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes
})
✅ Output Review Checklist
Páginas generadas bajo views/
Regiones repetidas extraídas en components/ (WorkoutCard aparece en 2 vistas)
Router compatible con Vue Router 4 (createWebHistory + lazy imports)
Componentes usan Vant 4 de forma consistente (van-cell, van-tag, van-nav-bar…)
Unidades CSS en px/vw, alineadas con mobile @3x baseline
Revisar copy de placeholder antes de commit (greeting, labels de stats)
Reemplazar fetch('/api/workouts/today') con llamada real a la API
Pasar por ESLint + Prettier + vue-tsc antes del primer commit