jcloude/dashboard/src/pages/ListPage.vue
2025-12-23 19:23:49 +08:00

171 lines
3.9 KiB
Vue

<template>
<div class="flex h-full flex-col">
<div class="sticky top-0 z-10 shrink-0">
<Header>
<Breadcrumbs
:items="[{ label: object.list.title, route: object.list.route }]"
/>
</Header>
</div>
<div class="p-5">
<AlertAddPaymentMode
class="mb-5"
v-if="$team?.pg && !$team.pg.payment_mode && !$team.pg.parent_team"
/>
<AlertCardExpired
class="mb-5"
v-if="$team?.pg && isCardExpired && $team.pg?.payment_mode == 'Card'"
/>
<AlertAddressDetails
class="mb-5"
v-if="
$team?.pg &&
!$team.pg?.billing_details?.name &&
$team.pg.payment_mode
"
/>
<CustomAlerts ctx_type="List Page" />
<AlertMandateInfo
class="mb-5"
v-if="
$team?.pg &&
isMandateNotSet &&
$team.pg.currency === 'INR' &&
$team.pg.payment_mode == 'Card'
"
/>
<AlertUnpaidInvoices
class="mb-5"
v-if="
hasUnpaidInvoices > 0 && $team.pg.payment_mode == 'Prepaid Credits'
"
:amount="hasUnpaidInvoices"
/>
<AlertBudgetThreshold
class="mb-5"
v-if="displayBudgetAlert > 0"
:amount="displayBudgetAlert"
:currency="$team.pg.currency == 'INR' ? '₹' : '$'"
/>
<ObjectList :options="listOptions" />
</div>
</div>
</template>
<script>
import Header from '../components/Header.vue';
import ObjectList from '../components/ObjectList.vue';
import { Breadcrumbs, Button, Dropdown, TextInput } from 'frappe-ui';
import { getObject } from '../objects';
import { defineAsyncComponent } from 'vue';
import dayjs from '../utils/dayjs';
export default {
components: {
Header,
Breadcrumbs,
ObjectList,
Button,
Dropdown,
TextInput,
AlertAddPaymentMode: defineAsyncComponent(
() => import('../components/AlertAddPaymentMode.vue'),
),
AlertCardExpired: defineAsyncComponent(
() => import('../components/AlertCardExpired.vue'),
),
AlertAddressDetails: defineAsyncComponent(
() => import('../components/AlertAddressDetails.vue'),
),
AlertMandateInfo: defineAsyncComponent(
() => import('../components/AlertMandateInfo.vue'),
),
AlertUnpaidInvoices: defineAsyncComponent(
() => import('../components/AlertUnpaidInvoices.vue'),
),
AlertBudgetThreshold: defineAsyncComponent(
() => import('../components/AlertBudgetThreshold.vue'),
),
CustomAlerts: defineAsyncComponent(
() => import('../components/CustomAlerts.vue'),
),
},
props: {
objectType: {
type: String,
required: true,
},
},
methods: {
getRoute(row) {
return {
name: `${this.object.doctype} Detail`,
params: {
name: row.name,
},
};
},
},
computed: {
object() {
return getObject(this.objectType);
},
listOptions() {
return {
...this.object.list,
doctype: this.object.doctype,
route: this.object.detail ? this.getRoute : null,
};
},
isCardExpired() {
if (this.$team.pg.payment_method?.expiry_year < dayjs().year()) {
return true;
} else if (
this.$team.pg.payment_method?.expiry_year == dayjs().year() &&
this.$team.pg.payment_method?.expiry_month < dayjs().month() + 1
) {
return true;
} else {
return false;
}
},
isMandateNotSet() {
return !this.$team.pg?.payment_method?.stripe_mandate_id;
},
hasUnpaidInvoices() {
return this.$resources.getAmountDue.data;
},
displayBudgetAlert() {
if (
!this.$team.pg.receive_budget_alerts ||
!this.$team.pg.monthly_alert_threshold ||
this.$team.pg.monthly_alert_threshold <= 0
) {
return 0;
}
let difference =
this.$resources.getCurrentBillingAmount.data -
this.$team.pg.monthly_alert_threshold;
return difference > 0 ? difference.toFixed(2) : 0;
},
},
resources: {
getAmountDue() {
return {
url: 'press.api.billing.total_unpaid_amount',
auto: true,
};
},
getCurrentBillingAmount() {
return {
url: 'press.api.billing.get_current_billing_amount',
auto: true,
cache: 'Current Billing Amount',
};
},
},
};
</script>