1import { apiGet, apiPost } from './api.js'; 2 3export async function openUsageModal() { 4 const subscriptionDetails = document.getElementById('subscriptionDetails'); 5 subscriptionDetails.innerHTML = '<p>Loading subscription details...</p>'; 6 const userInfo = JSON.parse(localStorage.getItem('userInfo')); 7 8 if (window.fbq) { 9 fbq('trackCustom', 'SubPageVisited', { 10 user_active_plan: userInfo?.subscription?.active_plan || 'none' 11 }); 12 } 13 14 try { 15 const data = await apiGet('subscription/v0/active_subscription/'); 16 if (data && data.active_plan) { 17 subscriptionDetails.innerHTML = `<div class="subscription-details"> 18<div class="row"> 19<p><strong>Active Plan:</strong> ${data.active_plan}</p> 20<p><strong>Status:</strong> ${data.status}</p> 21</div> 22<div class="row"> 23<p><strong>Start Date:</strong> ${new Date(data.start_date).toLocaleDateString()}</p> 24<p><strong>End Date:</strong> ${new Date(data.end_date).toLocaleDateString()}</p> 25</div> 26<p><strong>Image Message Usage:</strong> ${data.image_message_count}/${data.image_message_limit}</p> 27<p><strong>Text Message Usage:</strong> ${data.text_message_count}/${data.text_message_limit}</p> 28<p><strong>Voice Message Usage:</strong> ${data.voice_message_count}/${data.voice_message_limit}</p> 29<p><strong>AI Query Usage:</strong> ${data.ai_query_count}/${data.ai_query_limit}</p> 30<p><strong>Custom Category created:</strong> ${data.custom_category_count}/${data.custom_category_limit}</p> 31<p><strong>Input token usage:</strong> ${data.input_token_usage}</p> 32<p><strong>Output token usage:</strong> ${data.output_token_usage}</p> 33</div> 34<div class="text-center mt-4"> 35<button id="manageSubscriptionBtn" class="btn btn-outline-danger">Manage Subscription</button> 36</div>`; 37 38 // Add click listener for Manage Subscription 39 setTimeout(() => { 40 const manageBtn = document.getElementById('manageSubscriptionBtn'); 41 manageBtn?.addEventListener('click', async () => { 42 try { 43 const response = await apiPost('subscription/v0/cancel/', {}); 44 if (response.cancel_url) { 45 window.location.href = response.cancel_url; 46 } else { 47 alert('Unable to open billing portal.'); 48 } 49 } catch (err) { 50 console.error('Failed to redirect to Stripe portal:', err); 51 alert('Error redirecting to subscription management page.'); 52 } 53 }); 54 }, 0); 55 56 } else { 57 subscriptionDetails.innerHTML = '<p>No subscription details available.</p>'; 58 } 59 } catch (error) { 60 console.error('Error fetching subscription details:', error); 61 subscriptionDetails.innerHTML = '<p>Error loading subscription details.</p>'; 62 } 63 64 // Open the modal 65 const subscriptionModal = new bootstrap.Modal(document.getElementById('subscriptionModal')); 66 subscriptionModal.show(); 67}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.