Refactor shuttle and route management: price separation, premium preview design, and simplified route creation form

This commit is contained in:
2026-02-25 10:34:38 -05:00
parent 4bf75d3302
commit a9097b82d2
5 changed files with 534 additions and 159 deletions

View File

@ -20,8 +20,39 @@
<!-- CONTENT SIDE -->
<div class="content-side">
<!-- Route List -->
<!-- Route List & Create Form -->
<div v-if="!selectedRoute" class="route-list">
<!-- Create Form (Simplified) -->
<div v-if="isCreating" class="create-route-form nexus-glass">
<div class="form-header">
<span class="material-icons">route</span>
<h3>Nueva Ruta</h3>
</div>
<div class="form-body">
<div class="form-group">
<label>Punto de Salida</label>
<input v-model="newRouteForm.origin" type="text" placeholder="Ej: David">
</div>
<div class="form-group">
<label>Punto de Llegada</label>
<input v-model="newRouteForm.destination" type="text" placeholder="Ej: Boquete">
</div>
<div class="form-group">
<label>Nombre de Ruta (Auto)</label>
<input :value="computedRouteName" disabled type="text" placeholder="Salida - Llegada">
</div>
</div>
<div class="form-footer">
<button class="cancel-btn" @click="isCreating = false">Cancelar</button>
<button class="save-btn" :disabled="!isFormValid" @click="confirmCreateRoute">
<span class="material-icons">save</span> Guardar Ruta
</button>
</div>
</div>
<!-- Existing List -->
<div v-for="route in routes" :key="route.id" class="route-card" @click="selectRoute(route)">
<div class="route-info">
<h3>{{ route.name }}</h3>
@ -30,7 +61,7 @@
</div>
<span class="material-icons">chevron_right</span>
</div>
<div v-if="routes.length === 0" class="empty-state">No hay rutas registradas.</div>
<div v-if="routes.length === 0 && !isCreating" class="empty-state">No hay rutas registradas.</div>
</div>
<!-- Single Route Editor -->
@ -152,6 +183,20 @@ const allStops = ref<BusStop[]>([])
const selectedRoute = ref<Route | null>(null)
const routeStops = ref<BusStop[]>([])
const newStopId = ref('')
const isCreating = ref(false)
const newRouteForm = ref({
origin: '',
destination: ''
})
const computedRouteName = computed(() => {
if (!newRouteForm.value.origin || !newRouteForm.value.destination) return ''
return `${newRouteForm.value.origin} - ${newRouteForm.value.destination}`
})
const isFormValid = computed(() => {
return newRouteForm.value.origin.trim() !== '' && newRouteForm.value.destination.trim() !== ''
})
// Map integration
const { initMap, addNumberedMarker, addMarker, addPolyline, clearAllOverlays, isLoaded: mapsLoaded, map: gmap } = useGoogleMaps()
@ -291,19 +336,22 @@ function handleBack() {
}
async function createRoute() {
const name = prompt("Nombre de la nueva ruta:")
if (!name) return
isCreating.value = true
newRouteForm.value = { origin: '', destination: '' }
}
async function confirmCreateRoute() {
try {
const route = await routesService.createRoute({
name,
origin_city: 'David',
destination_city: 'Boquete',
await routesService.createRoute({
name: computedRouteName.value,
origin_city: newRouteForm.value.origin,
destination_city: newRouteForm.value.destination,
status: 'active',
color: '#FEE715',
direction: 'outbound'
})
routes.value = await routesService.getAllRoutes()
selectRoute(route)
isCreating.value = false
} catch (err: any) {
console.error('Error creating route:', err)
alert('No se pudo crear la ruta: ' + (err.response?.data?.detail || err.message))
@ -480,6 +528,74 @@ h1 { font-size: 1.5rem; font-weight: 800; color: #FEE715; margin: 0; }
.status.active { background: rgba(34, 197, 94, 0.1); color: #4ade80; }
.status.inactive { background: rgba(239, 68, 68, 0.1); color: #f87171; }
/* Nexus Create Form */
.create-route-form {
margin-bottom: 24px;
padding: 24px;
border-radius: 20px;
background: rgba(30, 41, 59, 0.5);
}
.nexus-glass {
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.form-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 20px;
color: #FEE715;
}
.form-header h3 {
margin: 0;
font-size: 1.1rem;
font-weight: 800;
}
.form-body {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 24px;
}
.form-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
.cancel-btn {
background: transparent;
border: 1px solid rgba(255,255,255,0.2);
color: white;
padding: 10px 20px;
border-radius: 10px;
font-weight: 700;
cursor: pointer;
}
.save-btn {
background: #FEE715;
color: #101820;
border: none;
padding: 10px 20px;
border-radius: 10px;
font-weight: 800;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
}
.save-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Editor View */
.route-editor {
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.1);