- Parte 3 : Viaggi
- Chat
This commit is contained in:
386
src/modules/viaggi/composables/useDriverProfile.ts
Normal file
386
src/modules/viaggi/composables/useDriverProfile.ts
Normal file
@@ -0,0 +1,386 @@
|
||||
import { ref, computed } from 'vue';
|
||||
import { Api } from '@api';
|
||||
import type {
|
||||
DriverProfile,
|
||||
Vehicle,
|
||||
UserPreferences,
|
||||
DriverPublicProfile
|
||||
} from '../types/viaggi.types';
|
||||
|
||||
// ============================================================
|
||||
// STATE
|
||||
// ============================================================
|
||||
|
||||
const driverProfile = ref<DriverPublicProfile | null>(null);
|
||||
const myDriverProfile = ref<DriverProfile | null>(null);
|
||||
const myVehicles = ref<Vehicle[]>([]);
|
||||
const myPreferences = ref<UserPreferences | null>(null);
|
||||
|
||||
const loading = ref(false);
|
||||
const error = ref<string | null>(null);
|
||||
|
||||
// ============================================================
|
||||
// COMPOSABLE
|
||||
// ============================================================
|
||||
|
||||
export function useDriverProfile() {
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// COMPUTED
|
||||
// ------------------------------------------------------------
|
||||
|
||||
const isDriver = computed(() => myDriverProfile.value?.isDriver ?? false);
|
||||
const hasVehicles = computed(() => myVehicles.value.length > 0);
|
||||
const defaultVehicle = computed(() =>
|
||||
myVehicles.value.find(v => v.isDefault) || myVehicles.value[0]
|
||||
);
|
||||
const averageRating = computed(() => myDriverProfile.value?.averageRating ?? 0);
|
||||
const totalRides = computed(() =>
|
||||
(myDriverProfile.value?.ridesCompletedAsDriver ?? 0) +
|
||||
(myDriverProfile.value?.ridesCompletedAsPassenger ?? 0)
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// API CALLS
|
||||
// ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Ottieni profilo pubblico di un conducente
|
||||
*/
|
||||
const fetchDriverProfile = async (userId: string) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
const response = await Api.SendReqWithData(
|
||||
`/api/viaggi/driver/user/${userId}`,
|
||||
'GET'
|
||||
);
|
||||
|
||||
if (response.success && response.data) {
|
||||
driverProfile.value = response.data;
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
error.value = err.message || 'Errore nel recupero del profilo';
|
||||
throw err;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Aggiorna il mio profilo conducente e/o preferenze
|
||||
*/
|
||||
const updateDriverProfile = async (data: {
|
||||
driverProfile?: Partial<DriverProfile>;
|
||||
preferences?: Partial<UserPreferences>;
|
||||
}) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
const response = await Api.SendReqWithData(
|
||||
'/api/viaggi/driver/profile',
|
||||
'PUT',
|
||||
{
|
||||
...data
|
||||
}
|
||||
);
|
||||
|
||||
if (response.success && response.data) {
|
||||
// Il backend ritorna user.profile che contiene driverProfile e preferences
|
||||
if (response.data.driverProfile) {
|
||||
myDriverProfile.value = response.data.driverProfile;
|
||||
}
|
||||
if (response.data.preferences) {
|
||||
myPreferences.value = response.data.preferences;
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
error.value = err.message || 'Errore nell\'aggiornamento del profilo';
|
||||
throw err;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Aggiorna solo le preferenze
|
||||
*/
|
||||
const updatePreferences = async (preferences: Partial<UserPreferences>) => {
|
||||
return await updateDriverProfile({ preferences });
|
||||
};
|
||||
|
||||
/**
|
||||
* Aggiungi veicolo
|
||||
*/
|
||||
const addVehicle = async (vehicleData: Omit<Vehicle, '_id'>) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
const response = await Api.SendReqWithData(
|
||||
'/api/viaggi/driver/vehicles',
|
||||
'POST',
|
||||
{ vehicle: vehicleData }
|
||||
);
|
||||
|
||||
if (response.success && response.data) {
|
||||
myVehicles.value = response.data;
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
error.value = err.message || 'Errore nell\'aggiunta del veicolo';
|
||||
throw err;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Aggiorna veicolo
|
||||
*/
|
||||
const updateVehicle = async (vehicleId: string, vehicleData: Partial<Vehicle>) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
const response = await Api.SendReqWithData(
|
||||
`/api/viaggi/driver/vehicles/${vehicleId}`,
|
||||
'PUT',
|
||||
{ vehicle: vehicleData }
|
||||
);
|
||||
|
||||
if (response.success && response.data) {
|
||||
myVehicles.value = response.data;
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
error.value = err.message || 'Errore nell\'aggiornamento del veicolo';
|
||||
throw err;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Rimuovi veicolo
|
||||
*/
|
||||
const removeVehicle = async (vehicleId: string) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
const response = await Api.SendReqWithData(
|
||||
`/api/viaggi/driver/vehicles/${vehicleId}`,
|
||||
'DELETE'
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
myVehicles.value = myVehicles.value.filter(v => v._id !== vehicleId);
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
error.value = err.message || 'Errore nella rimozione del veicolo';
|
||||
throw err;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Imposta veicolo predefinito
|
||||
*/
|
||||
const setDefaultVehicle = async (vehicleId: string) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
const response = await Api.SendReqWithData(
|
||||
`/api/viaggi/driver/vehicles/${vehicleId}/default`,
|
||||
'POST'
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
// Aggiorna localmente
|
||||
myVehicles.value = myVehicles.value.map(v => ({
|
||||
...v,
|
||||
isDefault: v._id === vehicleId
|
||||
}));
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
error.value = err.message || 'Errore nell\'impostazione del veicolo predefinito';
|
||||
throw err;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// UTILITIES
|
||||
// ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Formatta tipo veicolo
|
||||
*/
|
||||
const formatVehicleType = (type: string): string => {
|
||||
const types: Record<string, string> = {
|
||||
auto: '🚗 Auto',
|
||||
moto: '🏍️ Moto',
|
||||
furgone: '🚐 Furgone',
|
||||
minibus: '🚌 Minibus',
|
||||
altro: '🚙 Altro'
|
||||
};
|
||||
return types[type] || type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formatta veicolo completo
|
||||
*/
|
||||
const formatVehicle = (vehicle: Vehicle): string => {
|
||||
const parts = [];
|
||||
if (vehicle.brand) parts.push(vehicle.brand);
|
||||
if (vehicle.model) parts.push(vehicle.model);
|
||||
if (vehicle.color) parts.push(`(${vehicle.color})`);
|
||||
return parts.join(' ') || 'Veicolo';
|
||||
};
|
||||
|
||||
/**
|
||||
* Formatta response time
|
||||
*/
|
||||
const formatResponseTime = (time?: string): string => {
|
||||
const times: Record<string, string> = {
|
||||
within_hour: 'Entro un\'ora',
|
||||
within_day: 'Entro un giorno',
|
||||
within_days: 'Entro qualche giorno'
|
||||
};
|
||||
return times[time || 'within_day'] || 'N/D';
|
||||
};
|
||||
|
||||
/**
|
||||
* Formatta member since
|
||||
*/
|
||||
const formatMemberSince = (date?: Date | string): string => {
|
||||
if (!date) return 'N/D';
|
||||
const d = new Date(date);
|
||||
return d.toLocaleDateString('it-IT', { month: 'long', year: 'numeric' });
|
||||
};
|
||||
|
||||
/**
|
||||
* Calcola livello utente
|
||||
*/
|
||||
const calculateLevel = (points: number): { level: number; progress: number; nextLevel: number } => {
|
||||
const levels = [0, 100, 300, 600, 1000, 1500, 2500, 4000, 6000, 10000];
|
||||
let level = 1;
|
||||
|
||||
for (let i = 1; i < levels.length; i++) {
|
||||
if (points >= levels[i]) {
|
||||
level = i + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const currentLevelPoints = levels[level - 1] || 0;
|
||||
const nextLevelPoints = levels[level] || levels[levels.length - 1];
|
||||
const progress = ((points - currentLevelPoints) / (nextLevelPoints - currentLevelPoints)) * 100;
|
||||
|
||||
return {
|
||||
level,
|
||||
progress: Math.min(100, Math.max(0, progress)),
|
||||
nextLevel: nextLevelPoints
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Ottieni badge icon
|
||||
*/
|
||||
const getBadgeIcon = (badgeName: string): string => {
|
||||
const badges: Record<string, string> = {
|
||||
first_ride: '🎉',
|
||||
five_rides: '🚗',
|
||||
ten_rides: '🏆',
|
||||
fifty_rides: '⭐',
|
||||
hundred_rides: '👑',
|
||||
eco_warrior: '🌱',
|
||||
super_driver: '🦸',
|
||||
top_rated: '💯',
|
||||
fast_responder: '⚡',
|
||||
friendly: '😊'
|
||||
};
|
||||
return badges[badgeName] || '🏅';
|
||||
};
|
||||
|
||||
/**
|
||||
* Inizializza profilo dal user corrente (userStore)
|
||||
*/
|
||||
const initFromUser = (user: any) => {
|
||||
if (user?.profile?.driverProfile) {
|
||||
myDriverProfile.value = user.profile.driverProfile;
|
||||
myVehicles.value = user.profile.driverProfile.vehicles || [];
|
||||
}
|
||||
if (user?.profile?.preferences) {
|
||||
myPreferences.value = user.profile.preferences;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Pulisci stato
|
||||
*/
|
||||
const clearState = () => {
|
||||
driverProfile.value = null;
|
||||
myDriverProfile.value = null;
|
||||
myVehicles.value = [];
|
||||
myPreferences.value = null;
|
||||
error.value = null;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// RETURN
|
||||
// ------------------------------------------------------------
|
||||
|
||||
return {
|
||||
// State
|
||||
driverProfile,
|
||||
myDriverProfile,
|
||||
myVehicles,
|
||||
myPreferences,
|
||||
loading,
|
||||
error,
|
||||
|
||||
// Computed
|
||||
isDriver,
|
||||
hasVehicles,
|
||||
defaultVehicle,
|
||||
averageRating,
|
||||
totalRides,
|
||||
|
||||
// API Methods
|
||||
fetchDriverProfile,
|
||||
updateDriverProfile,
|
||||
updatePreferences,
|
||||
addVehicle,
|
||||
updateVehicle,
|
||||
removeVehicle,
|
||||
setDefaultVehicle,
|
||||
|
||||
// Utilities
|
||||
formatVehicleType,
|
||||
formatVehicle,
|
||||
formatResponseTime,
|
||||
formatMemberSince,
|
||||
calculateLevel,
|
||||
getBadgeIcon,
|
||||
initFromUser,
|
||||
clearState
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user