fix: refactor auth register to use pinia, clean up MapView obsolete telemetry call
This commit is contained in:
57
.github/workflows/deploy-frontend.yml
vendored
57
.github/workflows/deploy-frontend.yml
vendored
@ -1,57 +0,0 @@
|
|||||||
name: 🚀 Deploy Frontend → Firebase Hosting
|
|
||||||
|
|
||||||
# Se activa en cada push a la rama main
|
|
||||||
# SOLO cuando hay cambios en el frontend (no re-despliega si solo cambió el backend)
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'frontend/**'
|
|
||||||
- '.github/workflows/deploy-frontend.yml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-deploy:
|
|
||||||
name: Build & Deploy a Firebase
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: frontend
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# 1. Clonar el repositorio
|
|
||||||
- name: 📥 Checkout del repositorio
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# 2. Configurar Node.js
|
|
||||||
- name: ⚙️ Setup Node.js 22
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '22'
|
|
||||||
cache: 'npm'
|
|
||||||
cache-dependency-path: frontend/package-lock.json
|
|
||||||
|
|
||||||
# 3. Instalar dependencias
|
|
||||||
- name: 📦 Instalar dependencias (npm ci)
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
# 4. Crear el archivo .env.production con las variables del repositorio
|
|
||||||
# Estas variables las defines en: GitHub → Settings → Secrets and variables → Actions
|
|
||||||
- name: 🔐 Crear .env.production desde GitHub Secrets
|
|
||||||
run: |
|
|
||||||
echo "VITE_API_URL=${{ secrets.VITE_API_URL }}" > .env.production
|
|
||||||
echo "VITE_GOOGLE_MAPS_API_KEY=${{ secrets.VITE_GOOGLE_MAPS_API_KEY }}" >> .env.production
|
|
||||||
|
|
||||||
# 5. Compilar el frontend para producción
|
|
||||||
- name: 🔨 Build de producción (Vite)
|
|
||||||
run: npm run build
|
|
||||||
|
|
||||||
# 6. Deploy a Firebase Hosting
|
|
||||||
- name: 🚀 Deploy a Firebase Hosting
|
|
||||||
uses: FirebaseExtended/action-hosting-deploy@v0
|
|
||||||
with:
|
|
||||||
repoToken: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
|
|
||||||
channelId: live
|
|
||||||
projectId: sibu2-0-transport-2026
|
|
||||||
entryPoint: './frontend'
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"hosting": {
|
|
||||||
"public": "dist",
|
|
||||||
"cleanUrls": true,
|
|
||||||
"ignore": [
|
|
||||||
"firebase.json",
|
|
||||||
"**/.*",
|
|
||||||
"**/node_modules/**"
|
|
||||||
],
|
|
||||||
"rewrites": [
|
|
||||||
{
|
|
||||||
"source": "!{/__/**,/__}",
|
|
||||||
"destination": "/index.html"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8840
frontend/package-lock.json
generated
8840
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,6 @@
|
|||||||
"@tailwindcss/vite": "^4.2.0",
|
"@tailwindcss/vite": "^4.2.0",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"chart.js": "^4.5.1",
|
"chart.js": "^4.5.1",
|
||||||
"firebase": "^12.9.0",
|
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"jspdf": "^4.1.0",
|
"jspdf": "^4.1.0",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
@ -33,7 +32,6 @@
|
|||||||
"@vitejs/plugin-vue": "^6.0.1",
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
"@vue/tsconfig": "^0.8.1",
|
"@vue/tsconfig": "^0.8.1",
|
||||||
"autoprefixer": "^10.4.24",
|
"autoprefixer": "^10.4.24",
|
||||||
"firebase-tools": "^15.7.0",
|
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"tailwindcss": "^4.2.0",
|
"tailwindcss": "^4.2.0",
|
||||||
"typescript": "~5.9.3",
|
"typescript": "~5.9.3",
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { authService } from '@/services/authService'
|
|
||||||
import { analyticsService } from '@/services/analyticsService'
|
|
||||||
import { supabase } from '@/supabase'
|
import { supabase } from '@/supabase'
|
||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
|
import { analyticsService } from '@/services/analyticsService'
|
||||||
|
|
||||||
const emit = defineEmits(['toggle', 'success'])
|
const emit = defineEmits(['toggle', 'success'])
|
||||||
|
|
||||||
@ -22,42 +21,36 @@ const showPassword = ref(false)
|
|||||||
const handleRegister = async () => {
|
const handleRegister = async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
errorMessage.value = ''
|
errorMessage.value = ''
|
||||||
console.log('Intentando registrar usuario...')
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const cleanEmail = email.value.trim().toLowerCase()
|
const cleanEmail = email.value.trim().toLowerCase()
|
||||||
const cleanPass = password.value
|
const cleanPass = password.value
|
||||||
|
|
||||||
const regResponse = await authService.registerPassenger({
|
await authStore.register(cleanEmail, cleanPass, fullName.value.trim())
|
||||||
full_name: fullName.value.trim(),
|
|
||||||
email: cleanEmail,
|
|
||||||
password: cleanPass
|
|
||||||
})
|
|
||||||
console.log('Registro exitoso en Supabase:', regResponse)
|
|
||||||
|
|
||||||
analyticsService.logEvent({
|
analyticsService.logEvent({
|
||||||
event_name: 'sign_up',
|
event_name: 'sign_up',
|
||||||
properties: { method: 'email' }
|
properties: { method: 'email' }
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('Iniciando sesión automática...')
|
|
||||||
await authStore.login(cleanEmail, cleanPass)
|
|
||||||
|
|
||||||
successMessage.value = '¡Cuenta creada con éxito!'
|
successMessage.value = '¡Cuenta creada con éxito!'
|
||||||
|
|
||||||
setTimeout(() => {
|
// Delay navigation so user can see the success card
|
||||||
const r = authStore.role || 'PASSENGER'
|
setTimeout(() => {
|
||||||
navigateByUserRole(r)
|
navigateByUserRole(authStore.role || 'PASSENGER')
|
||||||
}, 1500)
|
}, 1500)
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Error detallado de registro:', error)
|
console.error('Error detallado de registro:', error)
|
||||||
errorMessage.value = `Error: ${error.message || 'Error desconocido'}`
|
if (error.message?.includes('User already registered') || error.message?.includes('already exists')) {
|
||||||
|
errorMessage.value = 'El correo ya está registrado.'
|
||||||
|
} else {
|
||||||
|
errorMessage.value = `Error: ${error.message || 'Error desconocido'}`
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigateByUserRole = (role: string) => {
|
const navigateByUserRole = (role: string) => {
|
||||||
const r = role.toUpperCase()
|
const r = role.toUpperCase()
|
||||||
if (r === 'ADMIN') router.push('/admin')
|
if (r === 'ADMIN') router.push('/admin')
|
||||||
|
|||||||
@ -51,6 +51,33 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function register(email: string, pass: string, fullName: string) {
|
||||||
|
console.log('Realizando signUp en Supabase...')
|
||||||
|
const { data, error } = await supabase.auth.signUp({
|
||||||
|
email,
|
||||||
|
password: pass,
|
||||||
|
options: {
|
||||||
|
data: {
|
||||||
|
full_name: fullName,
|
||||||
|
role: 'PASSENGER'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (error) throw new Error(error.message)
|
||||||
|
|
||||||
|
// Supabase retorna sesión inmediata si auto-confirm está activado.
|
||||||
|
if (data.session && data.user) {
|
||||||
|
userSession.value = data.session
|
||||||
|
userProfile.value = {
|
||||||
|
id: data.user.id,
|
||||||
|
email: data.user.email,
|
||||||
|
full_name: data.user.user_metadata?.full_name || data.user.email,
|
||||||
|
role: data.user.user_metadata?.role || 'PASSENGER'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
// Limpiar estado de Pinia inmediatamente
|
// Limpiar estado de Pinia inmediatamente
|
||||||
userSession.value = null
|
userSession.value = null
|
||||||
@ -84,6 +111,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
isPromoter,
|
isPromoter,
|
||||||
isPassenger,
|
isPassenger,
|
||||||
login,
|
login,
|
||||||
|
register,
|
||||||
logout
|
logout
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -208,7 +208,7 @@ async function claimPromo() {
|
|||||||
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
analyticsService.logEvent({ event_name: 'screen_view', screen_name: 'Map' })
|
analyticsService.logEvent({ event_name: 'screen_view', properties: { screen_name: 'Map' } })
|
||||||
// Add click outside listener
|
// Add click outside listener
|
||||||
document.addEventListener('click', handleClickOutside);
|
document.addEventListener('click', handleClickOutside);
|
||||||
|
|
||||||
@ -627,46 +627,7 @@ async function updateActiveUnits() {
|
|||||||
if (!isLoaded.value) return;
|
if (!isLoaded.value) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const units = await telemetryService.getActiveUnits();
|
// No-op for now. Backend is purely Supabase now.
|
||||||
console.log(`Fetched ${units.length} active units`);
|
|
||||||
|
|
||||||
// Create a set of current unit IDs to handle removals
|
|
||||||
const currentUnitIds = new Set(units.map(u => u.user_id));
|
|
||||||
|
|
||||||
// Remove markers for units that are no longer active
|
|
||||||
for (const [userId, marker] of unitMarkers.value.entries()) {
|
|
||||||
if (!currentUnitIds.has(userId)) {
|
|
||||||
marker.setMap(null);
|
|
||||||
unitMarkers.value.delete(userId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update or add markers for active units
|
|
||||||
units.forEach(unit => {
|
|
||||||
const existingMarker = unitMarkers.value.get(unit.user_id);
|
|
||||||
const position = { lat: unit.latitude, lng: unit.longitude };
|
|
||||||
|
|
||||||
if (existingMarker) {
|
|
||||||
// Move existing marker
|
|
||||||
existingMarker.setPosition(position);
|
|
||||||
} else {
|
|
||||||
// Create new unit marker
|
|
||||||
const isBus = unit.vehicle_type === 'bus';
|
|
||||||
const marker = addMarker(position, {
|
|
||||||
title: `${unit.full_name} (${unit.license_plate})`,
|
|
||||||
icon: {
|
|
||||||
path: isBus ? "M20 12h-2V4c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v15c0 1.1.9 2 2 2h1c0 1.1.9 2 2 2s2-.9 2-2h6c0 1.1.9 2 2 2s2-.9 2-2h1c1.1 0 2-.9 2-2v-7c0-1.1-.9-2-2-2zM6 19c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm12 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2-5h-2v-2h2v2z" : "M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z",
|
|
||||||
fillColor: isBus ? '#1976d2' : '#FEE715',
|
|
||||||
fillOpacity: 1,
|
|
||||||
strokeColor: '#000',
|
|
||||||
strokeWeight: 1,
|
|
||||||
scale: 1.5,
|
|
||||||
anchor: new google.maps.Point(12, 12)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (marker) unitMarkers.value.set(unit.user_id, marker);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to update active units', e);
|
console.error('Failed to update active units', e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,10 +97,6 @@ export default defineConfig(({ mode }) => {
|
|||||||
output: {
|
output: {
|
||||||
// Dividir código en chunks lógicos para cargas más rápidas en producción
|
// Dividir código en chunks lógicos para cargas más rápidas en producción
|
||||||
manualChunks: (id) => {
|
manualChunks: (id) => {
|
||||||
// Vendor: Firebase (bundle más pesado del stack)
|
|
||||||
if (id.includes('node_modules/firebase')) {
|
|
||||||
return 'vendor-firebase'
|
|
||||||
}
|
|
||||||
// Vendor: Charts y PDF (solo usados en vistas de Admin)
|
// Vendor: Charts y PDF (solo usados en vistas de Admin)
|
||||||
if (id.includes('node_modules/chart.js') || id.includes('node_modules/vue-chartjs')) {
|
if (id.includes('node_modules/chart.js') || id.includes('node_modules/vue-chartjs')) {
|
||||||
return 'vendor-charts'
|
return 'vendor-charts'
|
||||||
|
|||||||
Reference in New Issue
Block a user