796 lines
19 KiB
Vue
796 lines
19 KiB
Vue
<!-- MyFeedbackPage.vue -->
|
||
<template>
|
||
<q-page class="my-feedback-page">
|
||
<!-- Header -->
|
||
<div class="my-feedback-page__header">
|
||
<q-btn
|
||
flat
|
||
round
|
||
icon="arrow_back"
|
||
color="white"
|
||
@click="goBack"
|
||
/>
|
||
<div>
|
||
<h1>I Miei Feedback</h1>
|
||
<p>Le valutazioni che hai ricevuto</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Stats Summary -->
|
||
<div class="my-feedback-page__stats" v-if="!loading && stats">
|
||
<div class="my-feedback-page__rating-card">
|
||
<div class="my-feedback-page__rating-value">
|
||
{{ stats.averageRating?.toFixed(1) || '–' }}
|
||
</div>
|
||
<div class="my-feedback-page__rating-stars">
|
||
<q-icon
|
||
v-for="n in 5"
|
||
:key="n"
|
||
:name="n <= Math.round(stats.averageRating || 0) ? 'star' : 'star_border'"
|
||
:color="n <= Math.round(stats.averageRating || 0) ? 'amber' : 'grey-4'"
|
||
size="20px"
|
||
/>
|
||
</div>
|
||
<div class="my-feedback-page__rating-count">
|
||
{{ stats.totalCount || 0 }} valutazioni
|
||
</div>
|
||
</div>
|
||
|
||
<div class="my-feedback-page__stats-grid">
|
||
<div class="my-feedback-page__stat-item">
|
||
<q-icon name="directions_car" color="positive" size="24px" />
|
||
<span class="my-feedback-page__stat-value">{{ stats.asDriver || 0 }}</span>
|
||
<span class="my-feedback-page__stat-label">Come conducente</span>
|
||
</div>
|
||
<div class="my-feedback-page__stat-item">
|
||
<q-icon name="hail" color="info" size="24px" />
|
||
<span class="my-feedback-page__stat-value">{{ stats.asPassenger || 0 }}</span>
|
||
<span class="my-feedback-page__stat-label">Come passeggero</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tabs -->
|
||
<q-tabs
|
||
v-model="activeTab"
|
||
class="my-feedback-page__tabs"
|
||
active-color="primary"
|
||
indicator-color="primary"
|
||
align="justify"
|
||
>
|
||
<q-tab name="received" label="Ricevuti" icon="inbox" />
|
||
<q-tab name="given" label="Dati" icon="send" />
|
||
</q-tabs>
|
||
|
||
<!-- Content -->
|
||
<div class="my-feedback-page__content">
|
||
<!-- Loading -->
|
||
<div v-if="loading" class="my-feedback-page__loading">
|
||
<q-spinner-dots size="50px" color="primary" />
|
||
<p>Caricamento feedback...</p>
|
||
</div>
|
||
|
||
<!-- Empty State -->
|
||
<div v-else-if="filteredFeedbacks.length === 0" class="my-feedback-page__empty">
|
||
<q-icon
|
||
:name="activeTab === 'received' ? 'star_border' : 'rate_review'"
|
||
size="80px"
|
||
color="grey-4"
|
||
/>
|
||
<h3>{{ activeTab === 'received' ? 'Nessun feedback ricevuto' : 'Nessun feedback dato' }}</h3>
|
||
<p>
|
||
{{ activeTab === 'received'
|
||
? 'Completa i tuoi primi viaggi per ricevere valutazioni'
|
||
: 'Non hai ancora lasciato feedback ad altri utenti'
|
||
}}
|
||
</p>
|
||
<q-btn
|
||
color="primary"
|
||
icon="explore"
|
||
label="Esplora viaggi"
|
||
rounded
|
||
unelevated
|
||
to="/viaggi"
|
||
/>
|
||
</div>
|
||
|
||
<!-- Feedback List -->
|
||
<div v-else class="my-feedback-page__list">
|
||
<TransitionGroup name="list">
|
||
<div
|
||
v-for="feedback in filteredFeedbacks"
|
||
:key="feedback._id"
|
||
class="my-feedback-page__card"
|
||
>
|
||
<!-- Card Header -->
|
||
<div class="my-feedback-page__card-header">
|
||
<div class="my-feedback-page__user" @click="viewProfile(feedback)">
|
||
<q-avatar size="44px">
|
||
<img
|
||
v-if="getOtherUser(feedback)?.profile?.img"
|
||
:src="getOtherUser(feedback).profile.img"
|
||
/>
|
||
<div v-else class="my-feedback-page__avatar-placeholder">
|
||
{{ getInitials(getOtherUser(feedback)) }}
|
||
</div>
|
||
</q-avatar>
|
||
<div class="my-feedback-page__user-info">
|
||
<span class="my-feedback-page__user-name">
|
||
{{ getOtherUser(feedback)?.name }} {{ getOtherUser(feedback)?.surname }}
|
||
</span>
|
||
<span class="my-feedback-page__user-role">
|
||
<q-icon
|
||
:name="feedback.toUserRole === 'driver' ? 'directions_car' : 'hail'"
|
||
size="14px"
|
||
/>
|
||
{{ feedback.toUserRole === 'driver' ? 'Come conducente' : 'Come passeggero' }}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="my-feedback-page__rating">
|
||
<div class="my-feedback-page__rating-number">{{ feedback.rating }}</div>
|
||
<div class="my-feedback-page__rating-mini-stars">
|
||
<q-icon
|
||
v-for="n in 5"
|
||
:key="n"
|
||
:name="n <= feedback.rating ? 'star' : 'star_border'"
|
||
:color="n <= feedback.rating ? 'amber' : 'grey-4'"
|
||
size="12px"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Ride Info -->
|
||
<div
|
||
class="my-feedback-page__ride-info"
|
||
v-if="feedback.rideInfo"
|
||
@click="viewRide(feedback.rideId)"
|
||
>
|
||
<q-icon name="route" size="16px" color="grey-6" />
|
||
<span>{{ feedback.rideInfo.departure }} → {{ feedback.rideInfo.destination }}</span>
|
||
<span class="my-feedback-page__ride-date">
|
||
{{ formatDate(feedback.rideInfo.departureDate) }}
|
||
</span>
|
||
</div>
|
||
|
||
<!-- Categories -->
|
||
<div class="my-feedback-page__categories" v-if="feedback.categories?.length">
|
||
<div
|
||
v-for="cat in feedback.categories"
|
||
:key="cat.key"
|
||
class="my-feedback-page__category"
|
||
>
|
||
<span class="my-feedback-page__category-label">{{ cat.label }}</span>
|
||
<div class="my-feedback-page__category-stars">
|
||
<q-icon
|
||
v-for="n in 5"
|
||
:key="n"
|
||
:name="n <= cat.value ? 'star' : 'star_border'"
|
||
:color="n <= cat.value ? 'primary' : 'grey-4'"
|
||
size="14px"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tags -->
|
||
<div class="my-feedback-page__tags" v-if="feedback.tags?.length">
|
||
<q-chip
|
||
v-for="tag in feedback.tags"
|
||
:key="tag"
|
||
:color="getTagColor(tag)"
|
||
text-color="white"
|
||
size="sm"
|
||
dense
|
||
>
|
||
{{ tag }}
|
||
</q-chip>
|
||
</div>
|
||
|
||
<!-- Comment -->
|
||
<div class="my-feedback-page__comment" v-if="feedback.comment">
|
||
<q-icon name="format_quote" size="16px" color="grey-5" />
|
||
<p>{{ feedback.comment }}</p>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<div class="my-feedback-page__card-footer">
|
||
<span class="my-feedback-page__date">
|
||
{{ formatTimeAgo(feedback.createdAt) }}
|
||
</span>
|
||
<q-chip
|
||
v-if="feedback.isPublic"
|
||
color="green-1"
|
||
text-color="green-8"
|
||
size="sm"
|
||
icon="visibility"
|
||
dense
|
||
>
|
||
Pubblico
|
||
</q-chip>
|
||
<q-chip
|
||
v-else
|
||
color="grey-3"
|
||
text-color="grey-7"
|
||
size="sm"
|
||
icon="visibility_off"
|
||
dense
|
||
>
|
||
Privato
|
||
</q-chip>
|
||
</div>
|
||
</div>
|
||
</TransitionGroup>
|
||
|
||
<!-- Load More -->
|
||
<div v-if="hasMore" class="my-feedback-page__load-more">
|
||
<q-btn
|
||
flat
|
||
color="primary"
|
||
:loading="loadingMore"
|
||
@click="loadMore"
|
||
>
|
||
Carica altri
|
||
</q-btn>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</q-page>
|
||
</template>
|
||
|
||
<script lang="ts">
|
||
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;
|
||
totalCount: number;
|
||
asDriver: number;
|
||
asPassenger: number;
|
||
}
|
||
|
||
interface FeedbackCategory {
|
||
key: string;
|
||
label: string;
|
||
value: number;
|
||
}
|
||
|
||
interface FeedbackItem {
|
||
_id: string;
|
||
rideId: string;
|
||
fromUserId: string;
|
||
toUserId: string;
|
||
fromUser?: any;
|
||
toUser?: any;
|
||
toUserRole: 'driver' | 'passenger';
|
||
rating: number;
|
||
categories?: FeedbackCategory[];
|
||
tags?: string[];
|
||
comment?: string;
|
||
isPublic: boolean;
|
||
createdAt: string;
|
||
rideInfo?: {
|
||
departure: string;
|
||
destination: string;
|
||
departureDate: string;
|
||
type: string;
|
||
};
|
||
}
|
||
|
||
export default defineComponent({
|
||
name: 'MyFeedbackPage',
|
||
|
||
setup() {
|
||
const router = useRouter();
|
||
const $q = useQuasar();
|
||
|
||
// State
|
||
const loading = ref(true);
|
||
const loadingMore = ref(false);
|
||
const activeTab = ref<'received' | 'given'>('received');
|
||
const stats = ref<FeedbackStats | null>(null);
|
||
const receivedFeedbacks = ref<FeedbackItem[]>([]);
|
||
const givenFeedbacks = ref<FeedbackItem[]>([]);
|
||
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'
|
||
? receivedFeedbacks.value
|
||
: givenFeedbacks.value;
|
||
});
|
||
|
||
// Methods
|
||
const goBack = () => {
|
||
router.back();
|
||
};
|
||
|
||
const getInitials = (user: any) => {
|
||
if (!user) return '?';
|
||
const name = user.name || '';
|
||
const surname = user.surname || '';
|
||
return `${name.charAt(0)}${surname.charAt(0)}`.toUpperCase();
|
||
};
|
||
|
||
const getOtherUser = (feedback: FeedbackItem) => {
|
||
return activeTab.value === 'received' ? feedback.fromUser : feedback.toUser;
|
||
};
|
||
|
||
const formatDate = (dateStr: string) => {
|
||
return qdate.formatDate(dateStr, 'DD MMM YYYY');
|
||
};
|
||
|
||
const formatTimeAgo = (dateStr: string) => {
|
||
const now = new Date();
|
||
const date = new Date(dateStr);
|
||
const diffMs = now.getTime() - date.getTime();
|
||
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
||
|
||
if (diffDays === 0) return 'Oggi';
|
||
if (diffDays === 1) return 'Ieri';
|
||
if (diffDays < 7) return `${diffDays} giorni fa`;
|
||
if (diffDays < 30) return `${Math.floor(diffDays / 7)} settimane fa`;
|
||
return formatDate(dateStr);
|
||
};
|
||
|
||
const getTagColor = (tag: string): string => {
|
||
const positiveWords = ['puntuale', 'gentile', 'sicuro', 'pulito', 'preciso'];
|
||
const isPositive = positiveWords.some(w => tag.toLowerCase().includes(w));
|
||
return isPositive ? 'positive' : 'primary';
|
||
};
|
||
|
||
const viewProfile = (feedback: FeedbackItem) => {
|
||
const user = getOtherUser(feedback);
|
||
if (user?._id) {
|
||
router.push(`/viaggi/profilo/${user._id}`);
|
||
}
|
||
};
|
||
|
||
const viewRide = (rideId: string) => {
|
||
router.push(`/viaggi/ride/${rideId}`);
|
||
};
|
||
|
||
const loadFeedbacks = async () => {
|
||
loading.value = true;
|
||
|
||
try {
|
||
const [statsRes, receivedRes, givenRes] = await Promise.all([
|
||
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) {
|
||
stats.value = statsRes.data;
|
||
}
|
||
|
||
if (receivedRes.success) {
|
||
receivedFeedbacks.value = receivedRes.data.feedbacks || [];
|
||
hasMore.value = receivedRes.data.hasMore || false;
|
||
}
|
||
|
||
if (givenRes.success) {
|
||
givenFeedbacks.value = givenRes.data.feedbacks || [];
|
||
}
|
||
} catch (error: any) {
|
||
$q.notify({
|
||
type: 'negative',
|
||
message: error.data?.message || error.message || 'Errore nel caricamento dei feedback'
|
||
});
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
const loadMore = async () => {
|
||
loadingMore.value = true;
|
||
currentPage.value++;
|
||
|
||
try {
|
||
const endpoint = activeTab.value === 'received'
|
||
? '/api/viaggi/feedback/my/received'
|
||
: '/api/viaggi/feedback/my/given';
|
||
|
||
const response = await Api.SendReqWithData(`${endpoint}?page=${currentPage.value}`, 'GET');
|
||
|
||
if (response.success) {
|
||
const newFeedbacks = response.data.feedbacks || [];
|
||
|
||
if (activeTab.value === 'received') {
|
||
receivedFeedbacks.value.push(...newFeedbacks);
|
||
} else {
|
||
givenFeedbacks.value.push(...newFeedbacks);
|
||
}
|
||
|
||
hasMore.value = response.data.hasMore || false;
|
||
}
|
||
} catch (error: any) {
|
||
$q.notify({
|
||
type: 'negative',
|
||
message: 'Errore nel caricamento'
|
||
});
|
||
} finally {
|
||
loadingMore.value = false;
|
||
}
|
||
};
|
||
|
||
onMounted(() => {
|
||
loadFeedbacks();
|
||
});
|
||
|
||
return {
|
||
loading,
|
||
loadingMore,
|
||
activeTab,
|
||
stats,
|
||
filteredFeedbacks,
|
||
hasMore,
|
||
goBack,
|
||
getInitials,
|
||
getOtherUser,
|
||
formatDate,
|
||
formatTimeAgo,
|
||
getTagColor,
|
||
viewProfile,
|
||
viewRide,
|
||
loadMore
|
||
};
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.my-feedback-page {
|
||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||
min-height: 100vh;
|
||
padding-bottom: 80px;
|
||
|
||
// Header
|
||
&__header {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 16px 20px;
|
||
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;
|
||
}
|
||
}
|
||
|
||
// Stats
|
||
&__stats {
|
||
padding: 20px;
|
||
}
|
||
|
||
&__rating-card {
|
||
background: white;
|
||
border-radius: 16px;
|
||
padding: 24px;
|
||
text-align: center;
|
||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
&__rating-value {
|
||
font-size: 48px;
|
||
font-weight: 700;
|
||
color: #333;
|
||
line-height: 1;
|
||
}
|
||
|
||
&__rating-stars {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 4px;
|
||
margin: 8px 0;
|
||
}
|
||
|
||
&__rating-count {
|
||
color: #666;
|
||
font-size: 14px;
|
||
}
|
||
|
||
&__stats-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 12px;
|
||
}
|
||
|
||
&__stat-item {
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 16px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 8px;
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||
}
|
||
|
||
&__stat-value {
|
||
font-size: 24px;
|
||
font-weight: 700;
|
||
color: #333;
|
||
}
|
||
|
||
&__stat-label {
|
||
font-size: 12px;
|
||
color: #888;
|
||
text-align: center;
|
||
}
|
||
|
||
// Tabs
|
||
&__tabs {
|
||
background: white;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
// Content
|
||
&__content {
|
||
padding: 16px;
|
||
}
|
||
|
||
&__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;
|
||
}
|
||
}
|
||
|
||
// List
|
||
&__list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
}
|
||
|
||
// Card
|
||
&__card {
|
||
background: white;
|
||
border-radius: 16px;
|
||
padding: 16px;
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||
}
|
||
|
||
&__card-header {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: space-between;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
&__user {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
&__avatar-placeholder {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
font-weight: 600;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
&__user-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
}
|
||
|
||
&__user-name {
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
&__user-role {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
font-size: 12px;
|
||
color: #888;
|
||
}
|
||
|
||
&__rating {
|
||
text-align: right;
|
||
}
|
||
|
||
&__rating-number {
|
||
font-size: 24px;
|
||
font-weight: 700;
|
||
color: #ffc107;
|
||
line-height: 1;
|
||
}
|
||
|
||
&__rating-mini-stars {
|
||
display: flex;
|
||
gap: 1px;
|
||
}
|
||
|
||
// Ride Info
|
||
&__ride-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 10px 12px;
|
||
background: #f8f9fa;
|
||
border-radius: 8px;
|
||
font-size: 13px;
|
||
color: #555;
|
||
margin-bottom: 12px;
|
||
cursor: pointer;
|
||
|
||
&:hover {
|
||
background: #e9ecef;
|
||
}
|
||
}
|
||
|
||
&__ride-date {
|
||
margin-left: auto;
|
||
color: #888;
|
||
font-size: 12px;
|
||
}
|
||
|
||
// Categories
|
||
&__categories {
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
&__category {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 6px 0;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
}
|
||
|
||
&__category-label {
|
||
font-size: 13px;
|
||
color: #555;
|
||
}
|
||
|
||
&__category-stars {
|
||
display: flex;
|
||
gap: 2px;
|
||
}
|
||
|
||
// Tags
|
||
&__tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 6px;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
// Comment
|
||
&__comment {
|
||
display: flex;
|
||
gap: 8px;
|
||
padding: 12px;
|
||
background: #fafafa;
|
||
border-radius: 8px;
|
||
margin-bottom: 12px;
|
||
|
||
p {
|
||
margin: 0;
|
||
font-size: 14px;
|
||
color: #555;
|
||
font-style: italic;
|
||
line-height: 1.5;
|
||
}
|
||
}
|
||
|
||
// Footer
|
||
&__card-footer {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding-top: 12px;
|
||
border-top: 1px solid #f0f0f0;
|
||
}
|
||
|
||
&__date {
|
||
font-size: 12px;
|
||
color: #999;
|
||
}
|
||
|
||
// Load More
|
||
&__load-more {
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 20px;
|
||
}
|
||
}
|
||
|
||
// Transitions
|
||
.list-enter-active,
|
||
.list-leave-active {
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.list-enter-from,
|
||
.list-leave-to {
|
||
opacity: 0;
|
||
transform: translateY(20px);
|
||
}
|
||
|
||
// Dark Mode
|
||
.body--dark {
|
||
.my-feedback-page {
|
||
background: linear-gradient(135deg, #1a1a2e 0%, #16162a 100%);
|
||
|
||
&__rating-card,
|
||
&__stat-item,
|
||
&__card {
|
||
background: #1e1e30;
|
||
}
|
||
|
||
&__rating-value,
|
||
&__stat-value,
|
||
&__user-name {
|
||
color: #fff;
|
||
}
|
||
|
||
&__ride-info {
|
||
background: rgba(255, 255, 255, 0.05);
|
||
|
||
&:hover {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
}
|
||
|
||
&__comment {
|
||
background: rgba(255, 255, 255, 0.03);
|
||
}
|
||
|
||
&__card-footer {
|
||
border-color: rgba(255, 255, 255, 0.1);
|
||
}
|
||
}
|
||
}
|
||
</style>
|