diff --git a/apps/frontend/src/pages/settings/billing/index.vue b/apps/frontend/src/pages/settings/billing/index.vue index 3a2f87f043..02be05370c 100644 --- a/apps/frontend/src/pages/settings/billing/index.vue +++ b/apps/frontend/src/pages/settings/billing/index.vue @@ -800,13 +800,27 @@ const pyroSubscriptions = computed(() => { const pyroSubs = subscriptions.value?.filter((s) => s?.metadata?.type === 'pyro') || [] const servers = serversData.value?.servers || [] - return pyroSubs.map((subscription) => { - const server = servers.find((s) => s.server_id === subscription.metadata.id) - return { - ...subscription, - serverInfo: server, - } - }) + return pyroSubs + .map((subscription) => { + const server = servers.find((s) => s.server_id === subscription.metadata.id) + return { + ...subscription, + serverInfo: server, + } + }) + .filter((subscription) => { + // files expire 30 days after cancellation + const cancellationDate = getCancellationDate(subscription) + if ( + !cancellationDate || + subscription.serverInfo?.status !== 'suspended' || + subscription.serverInfo?.suspension_reason !== 'cancelled' + ) + return true + const cancellation = new Date(cancellationDate) + const thirtyDaysLater = new Date(cancellation.getTime() + 30 * 24 * 60 * 60 * 1000) + return new Date() <= thirtyDaysLater + }) }) const midasPurchaseModal = ref() @@ -919,14 +933,14 @@ const getProductFromPriceId = (priceId) => { return productsData.value.find((p) => p.prices?.some((x) => x.id === priceId)) } -const getPyroCharge = (subscription) => { +function getPyroCharge(subscription) { if (!subscription || !charges.value) return null return charges.value.find( (charge) => charge.subscription_id === subscription.id && charge.status !== 'succeeded', ) } -const getCancellationDate = (subscription) => { +function getCancellationDate(subscription) { const charge = getPyroCharge(subscription) if (!charge) return null if (charge.status === 'cancelled') return charge.due diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/index.vue b/packages/ui/src/layouts/wrapped/hosting/manage/index.vue index ec85dbc2a2..5078300524 100644 --- a/packages/ui/src/layouts/wrapped/hosting/manage/index.vue +++ b/packages/ui/src/layouts/wrapped/hosting/manage/index.vue @@ -453,13 +453,23 @@ function introToTop(array: Archon.Servers.v0.Server[]): Archon.Servers.v0.Server }) } +// files expire 30 days after cancellation +function filesExpired(server: Archon.Servers.v0.Server): boolean { + if (server.status !== 'suspended' || server.suspension_reason !== 'cancelled') return false + const cancellationDate = serverBillingMap.value.get(server.server_id)?.cancellationDate + if (!cancellationDate) return false + const cancellation = new Date(cancellationDate) + const thirtyDaysLater = new Date(cancellation.getTime() + 30 * 24 * 60 * 60 * 1000) + return new Date() > thirtyDaysLater +} + const filteredData = computed(() => { - if (!searchInput.value.trim()) { - return introToTop(serverList.value) - } - return fuse.value - ? introToTop(fuse.value.search(searchInput.value).map((result) => result.item)) - : [] + const base = !searchInput.value.trim() + ? introToTop(serverList.value) + : fuse.value + ? introToTop(fuse.value.search(searchInput.value).map((result) => result.item)) + : [] + return base.filter((server) => !filesExpired(server)) }) // Start polling only after initial data is available so the baseline is correct