From cd123ac36359ad2289a8179a21c15a478a61ff1c Mon Sep 17 00:00:00 2001 From: Surya Paolo Date: Wed, 24 Dec 2025 19:46:49 +0100 Subject: [PATCH] ancora parte 3 --- src/common/shared_vuejs.ts | 6 + src/components/CMyElem/CMyElem.ts | 2 + src/components/CMyElem/CMyElem.vue | 14 + .../widgets/{ => RideWidget}/RideWidget.scss | 0 .../widgets/{ => RideWidget}/RideWidget.ts | 2 +- .../widgets/{ => RideWidget}/RideWidget.vue | 0 .../components/widgets/RideWidget/index.ts | 1 + src/modules/viaggi/composables/useChat.ts | 2 +- src/modules/viaggi/composables/useRides.ts | 4 +- src/modules/viaggi/pages/ChatListPage.ts | 6 +- src/modules/viaggi/pages/DriverProfilePage.ts | 6 +- src/modules/viaggi/pages/MyRidesPage.ts | 7 +- src/modules/viaggi/pages/Myfeedbackpage.vue | 15 +- src/modules/viaggi/pages/Requestspage.vue | 770 ++++++++++++++---- src/modules/viaggi/pages/RideDetailPage.ts | 4 +- src/modules/viaggi/pages/RideSearchPage.ts | 4 +- src/modules/viaggi/pages/RidesListPage.ts | 6 +- 17 files changed, 683 insertions(+), 166 deletions(-) rename src/modules/viaggi/components/widgets/{ => RideWidget}/RideWidget.scss (100%) rename src/modules/viaggi/components/widgets/{ => RideWidget}/RideWidget.ts (98%) rename src/modules/viaggi/components/widgets/{ => RideWidget}/RideWidget.vue (100%) create mode 100644 src/modules/viaggi/components/widgets/RideWidget/index.ts diff --git a/src/common/shared_vuejs.ts b/src/common/shared_vuejs.ts index 96739c13..52145c23 100755 --- a/src/common/shared_vuejs.ts +++ b/src/common/shared_vuejs.ts @@ -194,6 +194,7 @@ export const shared_consts = { PAGERIS: 1620, CMYCIRCUITS: 1630, CREA_VOLANTINO: 1700, + VIAGGI_WIDGET: 1720, }, QUERYTYPE_MYGROUP: 1, @@ -2058,6 +2059,11 @@ export const shared_consts = { label: 'Genera Volantini', icon: 'fas fa-user-tie', }, + { + value: 1720, // VIAGGI_WIDGET + label: 'Widget Viaggi', + icon: 'fas fa-car-side', + }, { value: 120, label: 'OpenStreetMap', diff --git a/src/components/CMyElem/CMyElem.ts b/src/components/CMyElem/CMyElem.ts index 1de8431d..829577fb 100755 --- a/src/components/CMyElem/CMyElem.ts +++ b/src/components/CMyElem/CMyElem.ts @@ -33,6 +33,7 @@ import { LandingFooter } from '@/components/LandingFooter'; import { CMyActivities } from '@/components/CMyActivities'; import { CECommerce } from '@/components/CECommerce'; import { EventPosterGenerator } from '@/components/EventPosterGenerator'; +import { RideWidget } from 'app/src/modules/viaggi/components/widgets/RideWidget'; import { CheckEmail } from '@/components/CheckEmail'; import { HomeRiso } from '@/components/HomeRiso'; import mycircuits from '@/views/user/mycircuits/mycircuits.vue'; @@ -123,6 +124,7 @@ export default defineComponent({ CStatusReg, CDashboard, CheckEmail, + RideWidget, CMainView, CNotifAtTop, CPresentazione, diff --git a/src/components/CMyElem/CMyElem.vue b/src/components/CMyElem/CMyElem.vue index 621d1c5b..7439a8e5 100755 --- a/src/components/CMyElem/CMyElem.vue +++ b/src/components/CMyElem/CMyElem.vue @@ -154,6 +154,20 @@ +
+ ˚ +
+ VIAGGI +
+ + +
{ + const completeRideApi = async (rideId: string) => { try { loading.value = true; error.value = null; @@ -567,7 +567,7 @@ export function useRides() { createRide, updateRide, deleteRide, - completeRide, + completeRideApi, fetchMyRides, fetchStats, diff --git a/src/modules/viaggi/pages/ChatListPage.ts b/src/modules/viaggi/pages/ChatListPage.ts index 4426b227..5b9d84f0 100644 --- a/src/modules/viaggi/pages/ChatListPage.ts +++ b/src/modules/viaggi/pages/ChatListPage.ts @@ -350,13 +350,13 @@ export default defineComponent({ // ✅ Added: Start chat with user const startChatWith = async (user: User) => { try { - const chat = await getOrCreateDirectChat(user._id); + const response = await getOrCreateDirectChat(user._id); showUserSearch.value = false; userSearchQuery.value = ''; searchedUsers.value = []; - if (chat) { - router.push(`/viaggi/chat/${chat._id}`); + if (response?.data) { + router.push(`/viaggi/chat/${response.data._id}`); } } catch (error) { $q.notify({ diff --git a/src/modules/viaggi/pages/DriverProfilePage.ts b/src/modules/viaggi/pages/DriverProfilePage.ts index 1310303b..7212188f 100644 --- a/src/modules/viaggi/pages/DriverProfilePage.ts +++ b/src/modules/viaggi/pages/DriverProfilePage.ts @@ -6,6 +6,7 @@ import { useChat } from '../composables/useChat'; import RideCard from '../components/ride/RideCard.vue'; import FeedbackList from '../components/feedback/FeedbackList.vue'; import type { DriverPublicProfile } from '../types'; +import { useUserStore } from 'app/src/store'; export default defineComponent({ name: 'DriverProfilePage', @@ -33,10 +34,11 @@ export default defineComponent({ // Refs const ridesSection = ref(null); - const currentUserId = ref(''); // TODO: Get from auth + const userStore = useUserStore() + const currentUserId = ref(userStore.my._id); // Computed - const userId = computed(() => route.params.id as string); + const userId = computed(() => route.params.id ? route.params.id.toString() : currentUserId.value); const isOwnProfile = computed(() => userId.value === currentUserId.value); diff --git a/src/modules/viaggi/pages/MyRidesPage.ts b/src/modules/viaggi/pages/MyRidesPage.ts index 46918862..6dad3792 100644 --- a/src/modules/viaggi/pages/MyRidesPage.ts +++ b/src/modules/viaggi/pages/MyRidesPage.ts @@ -27,7 +27,7 @@ export default defineComponent({ loading, fetchMyRides, deleteRide, - completeRide: completeRideApi + completeRideApi, } = useRides(); const { @@ -159,10 +159,7 @@ export default defineComponent({ }; const openFeedbackDialog = (ride: Ride) => { - router.push({ - name: 'leave-feedback', - params: { rideId: ride._id } - }); + router.push(`/viaggi/feedback/viaggio/${ride._id}`); }; const acceptRequest = async (request: RideRequest) => { diff --git a/src/modules/viaggi/pages/Myfeedbackpage.vue b/src/modules/viaggi/pages/Myfeedbackpage.vue index a95d84c3..5a18dec8 100644 --- a/src/modules/viaggi/pages/Myfeedbackpage.vue +++ b/src/modules/viaggi/pages/Myfeedbackpage.vue @@ -245,6 +245,7 @@ import { defineComponent, ref, computed, onMounted } from 'vue'; import { useRouter } from 'vue-router'; import { useQuasar, date as qdate } from 'quasar'; import { Api } from '@api'; +import { useAuth } from '../composables/useAuth'; interface FeedbackStats { averageRating: number; @@ -298,6 +299,10 @@ export default defineComponent({ const currentPage = ref(1); const hasMore = ref(false); + const { user: currentUser } = useAuth(); + + const currentUserId = computed(() => currentUser.value?._id); + // Computed const filteredFeedbacks = computed(() => { return activeTab.value === 'received' @@ -360,9 +365,9 @@ export default defineComponent({ try { const [statsRes, receivedRes, givenRes] = await Promise.all([ - Api.SendReqWithData('/api/viaggi/feedback/stats', 'GET'), - Api.SendReqWithData('/api/viaggi/feedback/received', 'GET'), - Api.SendReqWithData('/api/viaggi/feedback/given', 'GET') + Api.SendReqWithData('/api/viaggi/feedback/user/' + currentUserId.value + '/stats', 'GET'), + Api.SendReqWithData('/api/viaggi/feedback/my/received', 'GET'), + Api.SendReqWithData('/api/viaggi/feedback/my/given', 'GET') ]); if (statsRes.success) { @@ -393,8 +398,8 @@ export default defineComponent({ try { const endpoint = activeTab.value === 'received' - ? '/api/viaggi/feedback/received' - : '/api/viaggi/feedback/given'; + ? '/api/viaggi/feedback/my/received' + : '/api/viaggi/feedback/my/given'; const response = await Api.SendReqWithData(`${endpoint}?page=${currentPage.value}`, 'GET'); diff --git a/src/modules/viaggi/pages/Requestspage.vue b/src/modules/viaggi/pages/Requestspage.vue index 6ec94cfd..f10f0000 100644 --- a/src/modules/viaggi/pages/Requestspage.vue +++ b/src/modules/viaggi/pages/Requestspage.vue @@ -3,7 +3,13 @@
- +

Richieste

Gestisci le richieste di passaggio

@@ -11,23 +17,38 @@
-
+
- +
{{ stats.pending }} In attesa
- +
{{ stats.accepted }} Accettate
- +
{{ stats.rejected }} Rifiutate @@ -36,20 +57,40 @@
- - + + - + @@ -65,7 +106,11 @@ clickable @click="activeFilter = filter.value" > - + {{ filter.label }}
@@ -73,35 +118,79 @@
-
- +
+

Caricamento richieste...

-
- +
+

{{ emptyTitle }}

{{ emptyMessage }}

- +
-
+
-
+
-
- +
+ {{ getStatusLabel(request.status) }}
-
+
- -
+ +
{{ getInitials(getOtherUser(request)) }}
@@ -109,17 +198,29 @@ {{ getOtherUser(request)?.name }} {{ getOtherUser(request)?.surname }} -
- +
+ {{ getOtherUser(request).rating.toFixed(1) }}
-
{{ formatTimeAgo(request.createdAt) }}
+
+ {{ formatTimeAgo(request.createdAt) }} +
-
+
- + {{ formatDate(request.rideInfo?.departureDate) }} - + {{ request.rideInfo?.departureTime }}
- +
-
-
- - {{ request.seats }} {{ request.seats === 1 ? 'posto' : 'posti' }} richiesti +
+
+ + {{ request.seats }} + {{ request.seats === 1 ? 'posto' : 'posti' }} richiesti
-
- +
+ {{ request.pickupPoint }}
-
- +
+

{{ request.message }}

-
- +
+

{{ request.response }}

-
- - +
+ +
-
- - +
+ +
-
- - +
+ +
-
- Carica altre +
+ Carica altre
- + - -

{{ responseAction === 'accept' ? 'Accetta richiesta' : 'Rifiuta richiesta' }}

+ +

+ {{ responseAction === 'accept' ? 'Accetta richiesta' : 'Rifiuta richiesta' }} +

- + - - - + + +
@@ -270,23 +508,30 @@ export default defineComponent({ { value: 'all', label: 'Tutte', icon: 'list' }, { value: 'pending', label: 'In attesa', icon: 'hourglass_empty' }, { value: 'accepted', label: 'Accettate', icon: 'check_circle' }, - { value: 'rejected', label: 'Rifiutate', icon: 'cancel' } + { value: 'rejected', label: 'Rifiutate', icon: 'cancel' }, ]; - const pendingReceivedCount = computed(() => receivedRequests.value.filter(r => r.status === 'pending').length); - const pendingSentCount = computed(() => sentRequests.value.filter(r => r.status === 'pending').length); + const pendingReceivedCount = computed( + () => receivedRequests.value.filter((r) => r.status === 'pending').length + ); + const pendingSentCount = computed( + () => sentRequests.value.filter((r) => r.status === 'pending').length + ); const filteredRequests = computed(() => { - const requests = activeTab.value === 'received' ? receivedRequests.value : sentRequests.value; + const requests = + activeTab.value === 'received' ? receivedRequests.value : sentRequests.value; if (activeFilter.value === 'all') return requests; - return requests.filter(r => r.status === activeFilter.value); + return requests.filter((r) => r.status === activeFilter.value); }); const emptyTitle = computed(() => { if (activeFilter.value !== 'all') { - return `Nessuna richiesta ${statusFilters.find(f => f.value === activeFilter.value)?.label.toLowerCase()}`; + return `Nessuna richiesta ${statusFilters.find((f) => f.value === activeFilter.value)?.label.toLowerCase()}`; } - return activeTab.value === 'received' ? 'Nessuna richiesta ricevuta' : 'Nessuna richiesta inviata'; + return activeTab.value === 'received' + ? 'Nessuna richiesta ricevuta' + : 'Nessuna richiesta inviata'; }); const emptyMessage = computed(() => { @@ -308,16 +553,27 @@ export default defineComponent({ }; const getStatusIcon = (status: string): string => { - const icons: Record = { pending: 'hourglass_empty', accepted: 'check_circle', rejected: 'cancel', cancelled: 'block' }; + const icons: Record = { + pending: 'hourglass_empty', + accepted: 'check_circle', + rejected: 'cancel', + cancelled: 'block', + }; return icons[status] || 'help'; }; const getStatusLabel = (status: string): string => { - const labels: Record = { pending: 'In attesa', accepted: 'Accettata', rejected: 'Rifiutata', cancelled: 'Annullata' }; + const labels: Record = { + pending: 'In attesa', + accepted: 'Accettata', + rejected: 'Rifiutata', + cancelled: 'Annullata', + }; return labels[status] || status; }; - const formatDate = (dateStr?: string) => dateStr ? qdate.formatDate(dateStr, 'DD MMM YYYY') : ''; + const formatDate = (dateStr?: string) => + dateStr ? qdate.formatDate(dateStr, 'DD MMM YYYY') : ''; const formatTimeAgo = (dateStr: string) => { const diffMs = Date.now() - new Date(dateStr).getTime(); @@ -343,7 +599,8 @@ export default defineComponent({ const openChat = (request: RideRequest) => { const user = getOtherUser(request); - if (user?._id) router.push(`/viaggi/chat?userId=${user._id}&rideId=${request.rideId}`); + if (user?._id) + router.push(`/viaggi/chat?userId=${user._id}&rideId=${request.rideId}`); }; const acceptRequest = (request: RideRequest) => { @@ -364,60 +621,101 @@ export default defineComponent({ if (!selectedRequest.value) return; responding.value = true; try { - const endpoint = responseAction.value === 'accept' - ? `/api/viaggi/richieste/${selectedRequest.value._id}/accept` - : `/api/viaggi/richieste/${selectedRequest.value._id}/reject`; - const response = await Api.SendReqWithData(endpoint, 'PUT', { message: responseMessage.value }); + const endpoint = + responseAction.value === 'accept' + ? `/api/viaggi/requests/${selectedRequest.value._id}/accept` + : `/api/viaggi/requests/${selectedRequest.value._id}/reject`; + const response = await Api.SendReqWithData(endpoint, 'PUT', { + message: responseMessage.value, + }); if (response.success) { - const index = receivedRequests.value.findIndex(r => r._id === selectedRequest.value?._id); + const index = receivedRequests.value.findIndex( + (r) => r._id === selectedRequest.value?._id + ); if (index !== -1) { - receivedRequests.value[index].status = responseAction.value === 'accept' ? 'accepted' : 'rejected'; + receivedRequests.value[index].status = + responseAction.value === 'accept' ? 'accepted' : 'rejected'; receivedRequests.value[index].response = responseMessage.value; } stats.value.pending = Math.max(0, stats.value.pending - 1); if (responseAction.value === 'accept') stats.value.accepted++; else stats.value.rejected++; - $q.notify({ type: 'positive', message: responseAction.value === 'accept' ? 'Richiesta accettata!' : 'Richiesta rifiutata' }); + $q.notify({ + type: 'positive', + message: + responseAction.value === 'accept' + ? 'Richiesta accettata!' + : 'Richiesta rifiutata', + }); showResponseDialog.value = false; } } catch (error: any) { - $q.notify({ type: 'negative', message: error.data?.message || error.message || 'Errore' }); + $q.notify({ + type: 'negative', + message: error.data?.message || error.message || 'Errore', + }); } finally { responding.value = false; } }; const cancelRequest = async (request: RideRequest) => { - $q.dialog({ title: 'Annulla richiesta', message: 'Sei sicuro?', cancel: true }).onOk(async () => { + $q.dialog({ + title: 'Annulla richiesta', + message: 'Sei sicuro?', + cancel: true, + }).onOk(async () => { try { - const response = await Api.SendReqWithData(`/api/viaggi/richieste/${request._id}/cancel`, 'PUT'); + const response = await Api.SendReqWithData( + `/api/viaggi/requests/${request._id}/cancel`, + 'PUT' + ); if (response.success) { - const index = sentRequests.value.findIndex(r => r._id === request._id); + const index = sentRequests.value.findIndex((r) => r._id === request._id); if (index !== -1) sentRequests.value[index].status = 'cancelled'; $q.notify({ type: 'positive', message: 'Richiesta annullata' }); } } catch (error: any) { - $q.notify({ type: 'negative', message: error.data?.message || error.message || 'Errore' }); + $q.notify({ + type: 'negative', + message: error.data?.message || error.message || 'Errore', + }); } }); }; + // Sostituisci la funzione loadRequests con questa versione corretta: + const loadRequests = async () => { loading.value = true; try { - const [statsRes, receivedRes, sentRes] = await Promise.all([ - Api.SendReqWithData('/api/viaggi/richieste/stats', 'GET'), - Api.SendReqWithData('/api/viaggi/richieste/received', 'GET'), - Api.SendReqWithData('/api/viaggi/richieste/sent', 'GET') + // ✅ Rimossa la chiamata a /api/viaggi/requests/stats che non esiste + const [receivedRes, sentRes] = await Promise.all([ + Api.SendReqWithData('/api/viaggi/requests/received', 'GET'), + Api.SendReqWithData('/api/viaggi/requests/sent', 'GET'), ]); - if (statsRes.success) stats.value = statsRes.data; + if (receivedRes.success) { receivedRequests.value = receivedRes.data.requests || []; hasMore.value = receivedRes.data.hasMore || false; } - if (sentRes.success) sentRequests.value = sentRes.data.requests || []; + + if (sentRes.success) { + sentRequests.value = sentRes.data.requests || []; + } + + // ✅ Calcola stats dai dati caricati + const allRequests = [...receivedRequests.value, ...sentRequests.value]; + stats.value = { + pending: allRequests.filter((r) => r.status === 'pending').length, + accepted: allRequests.filter((r) => r.status === 'accepted').length, + rejected: allRequests.filter((r) => r.status === 'rejected').length, + }; } catch (error: any) { - $q.notify({ type: 'negative', message: error.data?.message || error.message || 'Errore nel caricamento' }); + $q.notify({ + type: 'negative', + message: error.data?.message || error.message || 'Errore nel caricamento', + }); } finally { loading.value = false; } @@ -427,8 +725,14 @@ export default defineComponent({ loadingMore.value = true; currentPage.value++; try { - const endpoint = activeTab.value === 'received' ? '/api/viaggi/richieste/received' : '/api/viaggi/richieste/sent'; - const response = await Api.SendReqWithData(`${endpoint}?page=${currentPage.value}`, 'GET'); + const endpoint = + activeTab.value === 'received' + ? '/api/viaggi/requests/received' + : '/api/viaggi/requests/sent'; + const response = await Api.SendReqWithData( + `${endpoint}?page=${currentPage.value}`, + 'GET' + ); if (response.success) { const newRequests = response.data.requests || []; if (activeTab.value === 'received') receivedRequests.value.push(...newRequests); @@ -442,17 +746,47 @@ export default defineComponent({ } }; - watch(activeTab, () => { currentPage.value = 1; activeFilter.value = 'all'; }); + watch(activeTab, () => { + currentPage.value = 1; + activeFilter.value = 'all'; + }); onMounted(() => loadRequests()); return { - loading, loadingMore, responding, activeTab, activeFilter, stats, statusFilters, - filteredRequests, hasMore, pendingReceivedCount, pendingSentCount, emptyTitle, emptyMessage, - showResponseDialog, selectedRequest, responseAction, responseMessage, - goBack, getInitials, getOtherUser, getStatusIcon, getStatusLabel, formatDate, formatTimeAgo, - viewProfile, viewRide, openChat, acceptRequest, rejectRequest, submitResponse, cancelRequest, loadMore + loading, + loadingMore, + responding, + activeTab, + activeFilter, + stats, + statusFilters, + filteredRequests, + hasMore, + pendingReceivedCount, + pendingSentCount, + emptyTitle, + emptyMessage, + showResponseDialog, + selectedRequest, + responseAction, + responseMessage, + goBack, + getInitials, + getOtherUser, + getStatusIcon, + getStatusLabel, + formatDate, + formatTimeAgo, + viewProfile, + viewRide, + openChat, + acceptRequest, + rejectRequest, + submitResponse, + cancelRequest, + loadMore, }; - } + }, }); @@ -469,8 +803,16 @@ export default defineComponent({ display: flex; align-items: center; gap: 12px; - h1 { font-size: 20px; font-weight: 600; margin: 0; } - p { margin: 4px 0 0; opacity: 0.85; font-size: 14px; } + h1 { + font-size: 20px; + font-weight: 600; + margin: 0; + } + p { + margin: 4px 0 0; + opacity: 0.85; + font-size: 14px; + } } &__stats { @@ -487,35 +829,69 @@ export default defineComponent({ gap: 10px; } - &__stat-info { display: flex; flex-direction: column; } - &__stat-value { font-size: 20px; font-weight: 700; color: #333; } - &__stat-label { font-size: 11px; color: #888; } + &__stat-info { + display: flex; + flex-direction: column; + } + &__stat-value { + font-size: 20px; + font-weight: 700; + color: #333; + } + &__stat-label { + font-size: 11px; + color: #888; + } - &__tabs { background: white; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); } - &__tab-content { display: flex; align-items: center; gap: 6px; } + &__tabs { + background: white; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + } + &__tab-content { + display: flex; + align-items: center; + gap: 6px; + } &__filters { display: flex; gap: 8px; padding: 12px 16px; overflow-x: auto; - &::-webkit-scrollbar { display: none; } + &::-webkit-scrollbar { + display: none; + } } - &__content { padding: 16px; } + &__content { + padding: 16px; + } - &__loading, &__empty { + &__loading, + &__empty { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 60px 20px; text-align: center; - h3 { margin: 20px 0 8px; color: #333; font-size: 18px; } - p { color: #888; margin: 0 0 20px; max-width: 280px; } + h3 { + margin: 20px 0 8px; + color: #333; + font-size: 18px; + } + p { + color: #888; + margin: 0 0 20px; + max-width: 280px; + } } - &__list { display: flex; flex-direction: column; gap: 16px; } + &__list { + display: flex; + flex-direction: column; + gap: 16px; + } &__card { background: white; @@ -523,10 +899,19 @@ export default defineComponent({ padding: 16px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06); position: relative; - &--pending { border-left: 4px solid #ff9800; } - &--accepted { border-left: 4px solid #4caf50; } - &--rejected { border-left: 4px solid #f44336; } - &--cancelled { border-left: 4px solid #9e9e9e; opacity: 0.7; } + &--pending { + border-left: 4px solid #ff9800; + } + &--accepted { + border-left: 4px solid #4caf50; + } + &--rejected { + border-left: 4px solid #f44336; + } + &--cancelled { + border-left: 4px solid #9e9e9e; + opacity: 0.7; + } } &__status-badge { @@ -540,10 +925,22 @@ export default defineComponent({ border-radius: 20px; font-size: 11px; font-weight: 600; - &--pending { background: #fff3e0; color: #e65100; } - &--accepted { background: #e8f5e9; color: #2e7d32; } - &--rejected { background: #ffebee; color: #c62828; } - &--cancelled { background: #f5f5f5; color: #616161; } + &--pending { + background: #fff3e0; + color: #e65100; + } + &--accepted { + background: #e8f5e9; + color: #2e7d32; + } + &--rejected { + background: #ffebee; + color: #c62828; + } + &--cancelled { + background: #f5f5f5; + color: #616161; + } } &__card-header { @@ -554,7 +951,12 @@ export default defineComponent({ padding-right: 80px; } - &__user { display: flex; align-items: center; gap: 12px; cursor: pointer; } + &__user { + display: flex; + align-items: center; + gap: 12px; + cursor: pointer; + } &__avatar-placeholder { width: 100%; @@ -568,10 +970,26 @@ export default defineComponent({ border-radius: 50%; } - &__user-info { display: flex; flex-direction: column; gap: 2px; } - &__user-name { font-weight: 600; color: #333; } - &__user-rating { display: flex; align-items: center; gap: 4px; font-size: 12px; color: #666; } - &__date { font-size: 11px; color: #999; } + &__user-info { + display: flex; + flex-direction: column; + gap: 2px; + } + &__user-name { + font-weight: 600; + color: #333; + } + &__user-rating { + display: flex; + align-items: center; + gap: 4px; + font-size: 12px; + color: #666; + } + &__date { + font-size: 11px; + color: #999; + } &__ride { display: flex; @@ -582,7 +1000,9 @@ export default defineComponent({ border-radius: 10px; margin-bottom: 12px; cursor: pointer; - &:hover { background: #e9ecef; } + &:hover { + background: #e9ecef; + } } &__ride-type { @@ -595,24 +1015,58 @@ export default defineComponent({ border-radius: 10px; } - &__ride-details { flex: 1; } - &__ride-route { font-weight: 600; color: #333; margin-bottom: 4px; } - &__ride-datetime { display: flex; align-items: center; gap: 4px; font-size: 12px; color: #666; } + &__ride-details { + flex: 1; + } + &__ride-route { + font-weight: 600; + color: #333; + margin-bottom: 4px; + } + &__ride-datetime { + display: flex; + align-items: center; + gap: 4px; + font-size: 12px; + color: #666; + } - &__details { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 12px; } - &__detail { display: flex; align-items: center; gap: 6px; font-size: 13px; color: #555; } + &__details { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-bottom: 12px; + } + &__detail { + display: flex; + align-items: center; + gap: 6px; + font-size: 13px; + color: #555; + } - &__message, &__response { + &__message, + &__response { display: flex; gap: 8px; padding: 12px; background: #fafafa; border-radius: 8px; margin-bottom: 12px; - p { margin: 0; font-size: 13px; color: #555; line-height: 1.5; } + p { + margin: 0; + font-size: 13px; + color: #555; + line-height: 1.5; + } } - &__response { background: #e8f5e9; p { color: #2e7d32; } } + &__response { + background: #e8f5e9; + p { + color: #2e7d32; + } + } &__actions { display: flex; @@ -622,28 +1076,60 @@ export default defineComponent({ border-top: 1px solid #f0f0f0; } - &__load-more { display: flex; justify-content: center; padding: 20px; } + &__load-more { + display: flex; + justify-content: center; + padding: 20px; + } &__dialog { border-radius: 16px; min-width: 320px; max-width: 400px; - h3 { margin: 16px 0 8px; font-size: 18px; } + h3 { + margin: 16px 0 8px; + font-size: 18px; + } } } -.list-enter-active, .list-leave-active { transition: all 0.3s ease; } -.list-enter-from, .list-leave-to { opacity: 0; transform: translateY(20px); } +.list-enter-active, +.list-leave-active { + transition: all 0.3s ease; +} +.list-enter-from, +.list-leave-to { + opacity: 0; + transform: translateY(20px); +} .body--dark { .requests-page { background: linear-gradient(135deg, #1a1a2e 0%, #16162a 100%); - &__stats, &__card { background: #1e1e30; } - &__stat-value, &__user-name, &__ride-route { color: #fff; } - &__ride { background: rgba(255, 255, 255, 0.05); &:hover { background: rgba(255, 255, 255, 0.1); } } - &__ride-type { background: rgba(255, 255, 255, 0.1); } - &__message { background: rgba(255, 255, 255, 0.03); } - &__actions { border-color: rgba(255, 255, 255, 0.1); } + &__stats, + &__card { + background: #1e1e30; + } + &__stat-value, + &__user-name, + &__ride-route { + color: #fff; + } + &__ride { + background: rgba(255, 255, 255, 0.05); + &:hover { + background: rgba(255, 255, 255, 0.1); + } + } + &__ride-type { + background: rgba(255, 255, 255, 0.1); + } + &__message { + background: rgba(255, 255, 255, 0.03); + } + &__actions { + border-color: rgba(255, 255, 255, 0.1); + } } } diff --git a/src/modules/viaggi/pages/RideDetailPage.ts b/src/modules/viaggi/pages/RideDetailPage.ts index c46931fa..b98ae4c6 100644 --- a/src/modules/viaggi/pages/RideDetailPage.ts +++ b/src/modules/viaggi/pages/RideDetailPage.ts @@ -8,6 +8,7 @@ import { useFeedback } from '../composables/useFeedback'; import RideMap from '../components/ride/RideMap.vue'; import FeedbackList from '../components/feedback/FeedbackList.vue'; import type { Ride, UserBasic, Feedback } from '../types'; +import { useUserStore } from 'app/src/store'; export default defineComponent({ name: 'RideDetailPage', @@ -40,8 +41,9 @@ export default defineComponent({ const { getOrCreateDirectChat } = useChat(); const { fetchRideFeedback, feedbacks: rideFeedbacks } = useFeedback(); + const userStore = useUserStore() // State - const currentUserId = ref(''); // TODO: Get from auth + const currentUserId = ref(userStore.my._id); const loadingFeedbacks = ref(false); // Computed diff --git a/src/modules/viaggi/pages/RideSearchPage.ts b/src/modules/viaggi/pages/RideSearchPage.ts index 470c458c..cc6ac093 100644 --- a/src/modules/viaggi/pages/RideSearchPage.ts +++ b/src/modules/viaggi/pages/RideSearchPage.ts @@ -7,6 +7,7 @@ import { useChat } from '../composables/useChat'; import CityAutocomplete from '../components/ride/CityAutocomplete.vue'; import RideCard from '../components/ride/RideCard.vue'; import type { Ride, Location, RideType } from '../types'; +import { useUserStore } from 'app/src/store'; interface SearchParams { departure: Location | null; @@ -52,7 +53,8 @@ export default defineComponent({ const loadingMore = ref(false); const showAdvanced = ref(false); const sortBy = ref('date_asc'); - const currentUserId = ref(''); // TODO: Get from auth + const userStore = useUserStore() + const currentUserId = ref(userStore.my._id); const searchParams = reactive({ departure: null, diff --git a/src/modules/viaggi/pages/RidesListPage.ts b/src/modules/viaggi/pages/RidesListPage.ts index af6f2f53..9987f1bc 100644 --- a/src/modules/viaggi/pages/RidesListPage.ts +++ b/src/modules/viaggi/pages/RidesListPage.ts @@ -7,6 +7,7 @@ import { useChat } from '../composables/useChat'; import RideCard from '../components/ride/RideCard.vue'; import RideFilters from '../components/ride/RideFilters.vue'; import type { Ride, RideSearchFilters, RideType } from '../types'; +import { useUserStore } from 'app/src/store'; export default defineComponent({ name: 'RidesListPage', @@ -36,11 +37,10 @@ export default defineComponent({ const { getOrCreateDirectChat } = useChat(); // State + const userStore = useUserStore() const activeTab = ref<'all' | 'offers' | 'requests'>('all'); - const currentUserId = ref(''); // Da ottenere dal tuo auth store + const currentUserId = ref(userStore.my._id); - // TODO: Ottieni currentUserId dal tuo sistema di autenticazione - // Esempio: currentUserId.value = authStore.user?._id || ''; // Computed const filteredRides = computed(() => {