feat: Complete ATLAS system installation and API fixes

## Backend Changes
- Add new API endpoints: combustible, pois, mantenimiento, video, configuracion
- Fix vehiculos endpoint to return paginated response with items array
- Add /vehiculos/all endpoint for non-paginated list
- Add /geocercas/all endpoint
- Add /alertas/configuracion GET/PUT endpoints
- Add /viajes/activos and /viajes/iniciar endpoints
- Add /reportes/stats, /reportes/templates, /reportes/preview endpoints
- Add /conductores/all and /conductores/disponibles endpoints
- Update router.py to include all new modules

## Frontend Changes
- Fix authentication token handling (snake_case vs camelCase)
- Update vehiculosApi.listAll to use /vehiculos/all
- Fix FuelGauge component usage in Combustible page
- Fix chart component exports (named + default exports)
- Update API client for proper token refresh

## Infrastructure
- Rename services from ADAN to ATLAS
- Configure Cloudflare tunnel for atlas.consultoria-as.com
- Update systemd service files
- Configure PostgreSQL with TimescaleDB
- Configure Redis, Mosquitto, Traccar, MediaMTX

## Documentation
- Update installation guides
- Update API reference
- Rename all ADAN references to ATLAS

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
ATLAS Admin
2026-01-25 03:04:23 +00:00
parent 0dfce3ce20
commit e59aa2a742
73 changed files with 4415 additions and 450 deletions

View File

@@ -18,7 +18,7 @@ export const alertasApi = {
// Get active alerts
getActivas: (): Promise<Alerta[]> => {
return api.get<Alerta[]>('/alertas/activas')
return api.get<Alerta[]>('/alertas/pendientes')
},
// Get single alerta

View File

@@ -4,7 +4,7 @@ import { AuthResponse, LoginCredentials, User } from '@/types'
export const authApi = {
login: async (credentials: LoginCredentials): Promise<AuthResponse> => {
const response = await api.post<AuthResponse>('/auth/login', credentials)
setTokens(response.accessToken, response.refreshToken)
setTokens(response.access_token, response.refresh_token)
return response
},

View File

@@ -12,8 +12,8 @@ const apiClient: AxiosInstance = axios.create({
})
// Token storage
const TOKEN_KEY = 'adan_access_token'
const REFRESH_TOKEN_KEY = 'adan_refresh_token'
const TOKEN_KEY = 'atlas_access_token'
const REFRESH_TOKEN_KEY = 'atlas_refresh_token'
export const getAccessToken = (): string | null => {
return localStorage.getItem(TOKEN_KEY)
@@ -98,16 +98,16 @@ apiClient.interceptors.response.use(
try {
const response = await axios.post(`${API_BASE_URL}/auth/refresh`, {
refreshToken,
refresh_token: refreshToken,
})
const { accessToken, refreshToken: newRefreshToken } = response.data
setTokens(accessToken, newRefreshToken)
const { access_token, refresh_token } = response.data
setTokens(access_token, refresh_token)
processQueue(null, accessToken)
processQueue(null, access_token)
if (originalRequest.headers) {
originalRequest.headers.Authorization = `Bearer ${accessToken}`
originalRequest.headers.Authorization = `Bearer ${access_token}`
}
return apiClient(originalRequest)

View File

@@ -27,7 +27,7 @@ interface BarChartProps {
className?: string
}
export default function BarChart({
export function BarChart({
data,
bars,
xAxisKey,
@@ -118,6 +118,8 @@ export default function BarChart({
)
}
export default BarChart
// Simple horizontal bar with colors
interface SimpleBarProps {
data: Array<{

View File

@@ -9,7 +9,7 @@ interface FuelGaugeProps {
className?: string
}
export default function FuelGauge({
export function FuelGauge({
value,
maxValue = 100,
label = 'Combustible',
@@ -86,6 +86,8 @@ export default function FuelGauge({
)
}
export default FuelGauge
// Circular gauge variant
interface CircularGaugeProps {
value: number

View File

@@ -17,7 +17,7 @@ interface KPICardProps {
loading?: boolean
}
export default function KPICard({
export function KPICard({
title,
value,
subtitle,
@@ -134,6 +134,8 @@ interface MiniKPIProps {
color?: 'default' | 'blue' | 'green' | 'yellow' | 'red'
}
export default KPICard
export function MiniKPI({ label, value, icon, color = 'default' }: MiniKPIProps) {
const dotColors = {
default: 'bg-slate-500',

View File

@@ -26,7 +26,7 @@ interface LineChartProps {
className?: string
}
export default function LineChart({
export function LineChart({
data,
lines,
xAxisKey,
@@ -97,3 +97,5 @@ export default function LineChart({
</div>
)
}
export default LineChart

View File

@@ -95,7 +95,7 @@ export default function Sidebar() {
<MapPinIcon className="w-6 h-6 text-white" />
</div>
<div>
<h1 className="text-lg font-bold text-white">ADAN</h1>
<h1 className="text-lg font-bold text-white">ATLAS</h1>
<p className="text-xs text-slate-500">GPS Monitor</p>
</div>
</div>

View File

@@ -16,7 +16,7 @@ import Select from '@/components/ui/Select'
import { SkeletonCard } from '@/components/ui/Skeleton'
import { LineChart } from '@/components/charts/LineChart'
import { BarChart } from '@/components/charts/BarChart'
import { FuelGauge } from '@/components/charts/FuelGauge'
import { CircularGauge } from '@/components/charts/FuelGauge'
import { Combustible } from '@/types'
export default function CombustiblePage() {
@@ -247,7 +247,7 @@ export default function CombustiblePage() {
<Card padding="lg">
<CardHeader title="Rendimiento promedio" />
<div className="flex items-center justify-center h-[300px]">
<FuelGauge
<CircularGauge
value={stats.promedioRendimiento}
maxValue={20}
label="km/L"

View File

@@ -49,7 +49,7 @@ export default function Login() {
<MapPinIcon className="w-7 h-7 text-white" />
</div>
<div>
<h1 className="text-2xl font-bold text-white">ADAN GPS</h1>
<h1 className="text-2xl font-bold text-white">ATLAS GPS</h1>
<p className="text-sm text-slate-500">Sistema de Monitoreo</p>
</div>
</div>
@@ -138,7 +138,7 @@ export default function Login() {
{/* Footer */}
<p className="mt-8 text-center text-sm text-slate-600">
ADAN GPS v1.0.0 | Sistema de Monitoreo de Flota
ATLAS GPS v1.0.0 | Sistema de Monitoreo de Flota
</p>
</div>
</div>

View File

@@ -102,7 +102,7 @@ export const useAuthStore = create<AuthState>()(
setLoading: (loading: boolean) => set({ isLoading: loading }),
}),
{
name: 'adan-auth',
name: 'atlas-auth',
storage: createJSONStorage(() => localStorage),
partialize: (state) => ({
user: state.user,

View File

@@ -152,7 +152,7 @@ export const useConfigStore = create<ConfigState>()(
})),
}),
{
name: 'adan-config',
name: 'atlas-config',
storage: createJSONStorage(() => localStorage),
}
)

View File

@@ -252,7 +252,7 @@ export const useMapaStore = create<MapaStoreState>()(
},
}),
{
name: 'adan-mapa',
name: 'atlas-mapa',
storage: createJSONStorage(() => localStorage),
partialize: (state) => ({
centro: state.centro,

View File

@@ -40,10 +40,10 @@ export interface LoginCredentials {
}
export interface AuthResponse {
accessToken: string
refreshToken: string
access_token: string
refresh_token: string
user: User
expiresIn: number
expires_in: number
}
export interface TokenPayload {

10
frontend/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string
readonly VITE_WS_URL: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}