390 lines
14 KiB
Vue
390 lines
14 KiB
Vue
<script setup>
|
|
import { computed, onMounted, reactive, ref } from "vue";
|
|
import { useRoute, useRouter } from "vue-router";
|
|
import { useStore } from "vuex";
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const store = useStore();
|
|
const statusOptions = ["Active", "Cancelled"];
|
|
let filters = reactive({
|
|
status: [],
|
|
})
|
|
let foundText = ref('')
|
|
const subscriptions = ref([]);
|
|
const search = ref("");
|
|
const filteredSubscriptions = computed(() => {
|
|
let subscriptionList = store.getters.getsubscriptionList;
|
|
|
|
// Check if subscriptionList is null or undefined
|
|
if (!subscriptionList) {
|
|
return [];
|
|
}
|
|
|
|
subscriptions.value = subscriptionList;
|
|
|
|
if (filters.status.length > 0) {
|
|
foundText.value = filters.status.join(', ')
|
|
subscriptionList = subscriptionList.filter((order) =>
|
|
filters.status.includes(order.status)
|
|
);
|
|
}
|
|
|
|
console.log('subscriptionList', subscriptionList)
|
|
const searchLower = search.value.toLowerCase();
|
|
console.log(searchLower)
|
|
|
|
return subscriptionList.filter(
|
|
(sub) =>
|
|
(sub.order_number && String(sub.order_number).toLowerCase().includes(searchLower)) ||
|
|
(sub.product_title && String(sub.product_title).toLowerCase().includes(searchLower))
|
|
);
|
|
});
|
|
const formatDate = (date) => {
|
|
const messageDate = new Date(date);
|
|
const options = {
|
|
year: "numeric",
|
|
month: "numeric",
|
|
day: "numeric",
|
|
|
|
};
|
|
const formattedDate = messageDate
|
|
.toLocaleString("en-US", options)
|
|
.replace(/\//g, "-");
|
|
return `${formattedDate} `;
|
|
};
|
|
const getStatusColor = (status) => {
|
|
if (status === "Active") return "green";
|
|
if (status === "Cancelled") return "orange";
|
|
return "red";
|
|
};
|
|
const getStatusIcon = (status) => {
|
|
switch (status.toLowerCase()) {
|
|
case 'active':
|
|
return 'mdi-check-circle';
|
|
case 'pending':
|
|
return 'mdi-clock-outline';
|
|
case 'cancelled':
|
|
return 'mdi-cancel';
|
|
case 'expired':
|
|
return 'mdi-alert-circle-outline';
|
|
default:
|
|
return 'mdi-help-circle-outline';
|
|
}
|
|
}
|
|
const viewDetails = (subscription) => {
|
|
// Implement view details logic here
|
|
console.log("View details for subscription:", subscription.id);
|
|
router.push("/subscriptions-detail/" + subscription.id);
|
|
};
|
|
const subscriptionList = computed(() => {
|
|
let filtered = store.getters.getsubscriptionList;
|
|
subscriptions.value = store.getters.getsubscriptionList;
|
|
|
|
return subscriptions.value;
|
|
});
|
|
onMounted(async () => {
|
|
store.dispatch("updateIsLoading", true);
|
|
await store.dispatch("subscriptionList");
|
|
});
|
|
const getPlanIcon = (plan) => {
|
|
switch (plan.toLowerCase()) {
|
|
case "basic":
|
|
return "mdi-star-outline";
|
|
case "premium":
|
|
return "mdi-star-half";
|
|
case "pro":
|
|
return "mdi-star";
|
|
case "enterprise":
|
|
return "mdi-medal";
|
|
default:
|
|
return "mdi-help-circle";
|
|
}
|
|
};
|
|
const cancelSubscription = async (subscriptionData) => {
|
|
// Implement cancellation logic here
|
|
store.dispatch("updateIsLoading", true);
|
|
await store.dispatch("subscriptionCancel", { id: subscriptionData.subscription_id });
|
|
console.log("Cancelling subscription:", subscriptionData.subscription_id);
|
|
await store.dispatch("subscriptionList");
|
|
await store.getters.getsubscriptionList;
|
|
store.dispatch("updateIsLoading", false);
|
|
};
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<VDialog v-model="store.getters.getIsLoading" width="110" height="150" color="primary">
|
|
<VCardText class="" style="color: white !important">
|
|
<div class="demo-space-x">
|
|
<VProgressCircular :size="40" color="primary" indeterminate />
|
|
</div>
|
|
</VCardText>
|
|
</VDialog>
|
|
<v-container fluid class="subscription-container pa-6">
|
|
<v-row justify="center" align="center" class="mb-8" style="display: none;">
|
|
<v-col cols="12" md="8">
|
|
<h4 class="text-h4 text-center gradient-text mb-4">
|
|
Active Subscriptions
|
|
</h4>
|
|
<v-text-field v-model="search" prepend-inner-icon="mdi-magnify" label="Search subscriptions" outlined
|
|
rounded hide-details dense class="search-field"></v-text-field>
|
|
|
|
</v-col>
|
|
</v-row>
|
|
<v-row>
|
|
<v-col cols="12">
|
|
|
|
<VCardTitle class="pt-0"><b>Subscriptions </b></VCardTitle>
|
|
<v-card>
|
|
<v-card-title>
|
|
<v-row class="px-0 py-4">
|
|
|
|
|
|
<v-col cols="12" md="4">
|
|
<v-text-field v-model="search" prepend-inner-icon="mdi-magnify"
|
|
label="Search subscriptions" outlined density="compact" hide-details
|
|
class="search-field"></v-text-field>
|
|
</v-col>
|
|
<v-col cols="12" md="4">
|
|
<v-select v-model="filters.status" :items="statusOptions" label="Status" outlined
|
|
density="compact" multiple></v-select>
|
|
</v-col>
|
|
|
|
|
|
</v-row>
|
|
</v-card-title>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
<v-row v-if="filteredSubscriptions.length > 0">
|
|
|
|
<VCol sm="6" cols="12" v-for="subscription in filteredSubscriptions" :key="subscription.order_number"
|
|
style="display: none;">
|
|
<VCard>
|
|
<div class="d-flex justify-space-between flex-wrap flex-md-nowrap flex-column flex-md-row">
|
|
<div class="ma-auto pa-5">
|
|
<VImg width="137" height="176" :src="subscription.image_url" />
|
|
</div>
|
|
|
|
<VDivider :vertical="$vuetify.display.mdAndUp" />
|
|
|
|
<div>
|
|
<VCardItem>
|
|
|
|
</VCardItem>
|
|
|
|
<VCardText>
|
|
<h3>{{ subscription }}</h3>
|
|
</VCardText>
|
|
|
|
<VCardText class="text-subtitle-1">
|
|
<span>Price :</span> <span class="font-weight-medium">${{
|
|
subscription.product_price.amount }}</span>
|
|
<span v-if="subscription.subscription_start_date">Start :</span> <span
|
|
class="font-weight-medium" v-if="subscription.subscription_start_date">{{
|
|
formatDate(subscription.subscription_start_date)
|
|
}}</span>
|
|
<span v-if="subscription.subscription_renewal_date">Renewal Date :</span> <span
|
|
class="font-weight-medium" v-if="subscription.subscription_renewal_date">{{
|
|
formatDate(subscription.subscription_renewal_date)
|
|
}}</span>
|
|
<span>Status :</span> <span class="font-weight-medium">{{
|
|
subscription.status }}</span>
|
|
</VCardText>
|
|
|
|
<VCardActions class="justify-space-between">
|
|
<VBtn>
|
|
<VIcon icon="bx-cart-add" />
|
|
<span class="ms-2">Add to cart</span>
|
|
</VBtn>
|
|
|
|
<VBtn color="secondary" icon="bx-share-alt" />
|
|
</VCardActions>
|
|
</div>
|
|
</div>
|
|
</VCard>
|
|
</VCol>
|
|
|
|
<v-col v-for="subscription in filteredSubscriptions" :key="subscription.order_number" cols="12" md="4">
|
|
<v-hover v-slot:default="{ isHovering }">
|
|
<v-card class="subscription-card mx-auto" :elevation="isHovering ? 8 : 2"
|
|
:class="{ 'on-hover': isHovering }">
|
|
<v-card-title class="text-h5 d-flex flex-column align-center">
|
|
<v-avatar size="80" class="mb-3" color="rgb(var(--v-theme-yellow))"
|
|
v-if="subscription.image_url">
|
|
<v-img :src="subscription.image_url" :alt="subscription.title"></v-img>
|
|
|
|
</v-avatar>
|
|
<v-avatar color="rgb(var(--v-theme-yellow))" size="56" v-if="!subscription.image_url"
|
|
class="text-grey-800 text-h6 font-weight-bold mr-4">
|
|
#{{ subscription.order_number }}
|
|
</v-avatar>
|
|
</v-card-title>
|
|
<v-card-text>
|
|
<h4 class="text-center title">{{ subscription.product_title }}</h4>
|
|
<v-list dense class="details-list">
|
|
<v-list-item>
|
|
<v-row align="center" no-gutters>
|
|
<v-col cols="12" md="2">
|
|
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="8">
|
|
<v-icon color="primary">mdi-cash</v-icon> <span>Price: ${{
|
|
subscription.product_price.amount }}</span>
|
|
</v-col>
|
|
<v-col cols="12" md="2">
|
|
|
|
</v-col>
|
|
</v-row>
|
|
</v-list-item>
|
|
<v-list-item v-if="subscription.subscription_start_date">
|
|
<v-row align="center" no-gutters>
|
|
<v-col cols="12" md="2">
|
|
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="8">
|
|
<v-icon color="primary">mdi-calendar-start</v-icon><span>Start: {{
|
|
formatDate(subscription.subscription_start_date) }}</span>
|
|
</v-col>
|
|
<v-col cols="12" md="2">
|
|
|
|
</v-col>
|
|
</v-row>
|
|
</v-list-item>
|
|
<v-list-item v-if="subscription.subscription_renewal_date">
|
|
<v-row align="center" no-gutters>
|
|
<v-col cols="12" md="2">
|
|
|
|
</v-col>
|
|
<v-col cols="12" md="8">
|
|
<v-icon color="primary">mdi-calendar-clock</v-icon> <span>Next Billing: {{
|
|
formatDate(subscription.subscription_renewal_date) }}</span>
|
|
</v-col>
|
|
<v-col cols="12" md="2">
|
|
|
|
</v-col>
|
|
</v-row>
|
|
</v-list-item>
|
|
<v-list-item>
|
|
<v-row align="center" no-gutters>
|
|
<v-col cols="12" md="2">
|
|
|
|
</v-col>
|
|
<v-col cols="12" md="8">
|
|
<v-icon :color="getStatusColor(subscription.status)">
|
|
{{ getStatusIcon(subscription.status) }}
|
|
</v-icon>
|
|
<span>Status: {{ subscription.status }}</span>
|
|
</v-col>
|
|
<v-col cols="12" md="2">
|
|
|
|
</v-col>
|
|
</v-row>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-btn color="rgb(var(--v-theme-yellow))" @click="cancelSubscription(subscription)"
|
|
prepend-icon="mdi-cancel" block>Cancel
|
|
Subscription</v-btn>
|
|
<v-btn color="primary" block @click="viewDetails(subscription)">
|
|
View Details
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</v-hover>
|
|
</v-col>
|
|
|
|
</v-row>
|
|
<v-row v-else justify="center" align="center">
|
|
<v-col cols="12" class="text-center">
|
|
<v-icon size="64" color="grey">mdi-playlist-remove</v-icon>
|
|
<h3 class="mt-4">No {{ foundText }} Subscriptions</h3>
|
|
<p class="text-subtitle-1">You don't have any {{foundText}} subscriptions at the moment.</p>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
</template>
|
|
<style scoped>
|
|
.subscription-container {
|
|
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.subscription-card {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.subscription-card.on-hover {
|
|
transform: translateY(-5px);
|
|
}
|
|
|
|
.v-avatar {
|
|
background-color: var(--v-primary-base);
|
|
}
|
|
|
|
.subscription-container .v-card .v-card-text {
|
|
line-height: 1.25rem;
|
|
min-height: 200px;
|
|
}
|
|
|
|
.title {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.gradient-text {
|
|
background: linear-gradient(45deg, rgb(var(--v-theme-yellow)), #173320);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.search-field {
|
|
max-width: 500px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.subscription-card {
|
|
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
border-radius: 16px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.subscription-card.on-hover {
|
|
transform: translateY(-5px);
|
|
}
|
|
|
|
.v-list-item {
|
|
min-height: 40px;
|
|
}
|
|
|
|
.details-list .v-list-item {
|
|
padding: 0;
|
|
}
|
|
|
|
.details-list .v-row {
|
|
align-items: center;
|
|
}
|
|
|
|
.details-list .v-col {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.details-list .v-icon {
|
|
margin-right: 0.5rem;
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
.details-list .v-col span {
|
|
font-size: 1rem;
|
|
font-weight: 500;
|
|
color: var(--v-grey-darken1);
|
|
}
|
|
</style>
|