210 lines
5.8 KiB
JavaScript
210 lines
5.8 KiB
JavaScript
window.app = Vue.createApp({
|
|
el: '#dcaClient',
|
|
mixins: [windowMixin],
|
|
delimiters: ['${', '}'],
|
|
data: function () {
|
|
return {
|
|
dashboardData: null,
|
|
transactions: [],
|
|
loading: true,
|
|
error: null,
|
|
showFiatValues: false, // Hide fiat values by default
|
|
transactionColumns: [
|
|
{
|
|
name: 'date',
|
|
label: 'Date',
|
|
align: 'left',
|
|
field: row => row.transaction_time || row.created_at,
|
|
sortable: false
|
|
},
|
|
{
|
|
name: 'amount_sats',
|
|
label: 'Bitcoin',
|
|
align: 'right',
|
|
field: 'amount_sats',
|
|
sortable: false
|
|
},
|
|
{
|
|
name: 'amount_fiat',
|
|
label: 'Fiat Amount',
|
|
align: 'right',
|
|
field: 'amount_fiat',
|
|
sortable: false
|
|
},
|
|
{
|
|
name: 'type',
|
|
label: 'Type',
|
|
align: 'center',
|
|
field: 'transaction_type',
|
|
sortable: false
|
|
},
|
|
{
|
|
name: 'status',
|
|
label: 'Status',
|
|
align: 'center',
|
|
field: 'status',
|
|
sortable: false
|
|
}
|
|
],
|
|
transactionPagination: {
|
|
sortBy: 'date',
|
|
descending: true,
|
|
page: 1,
|
|
rowsPerPage: 10
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
formatCurrency(amount) {
|
|
if (!amount) return 'Q 0.00';
|
|
// Values are already in full currency units, not centavos
|
|
return new Intl.NumberFormat('es-GT', {
|
|
style: 'currency',
|
|
currency: 'GTQ',
|
|
}).format(amount);
|
|
},
|
|
|
|
formatCurrencyWithCode(amount, currencyCode) {
|
|
if (!amount) return `${currencyCode} 0.00`;
|
|
// Format with the provided currency code
|
|
try {
|
|
return new Intl.NumberFormat('en-US', {
|
|
style: 'currency',
|
|
currency: currencyCode,
|
|
}).format(amount);
|
|
} catch (error) {
|
|
// Fallback if currency code is not supported
|
|
return `${currencyCode} ${amount.toFixed(2)}`;
|
|
}
|
|
},
|
|
|
|
formatDate(dateString) {
|
|
if (!dateString) return ''
|
|
return new Date(dateString).toLocaleDateString()
|
|
},
|
|
|
|
formatTime(dateString) {
|
|
if (!dateString) return ''
|
|
return new Date(dateString).toLocaleTimeString('en-US', {
|
|
hour: '2-digit',
|
|
minute: '2-digit'
|
|
})
|
|
},
|
|
|
|
formatSats(amount) {
|
|
if (!amount) return '0 sats'
|
|
const formatted = new Intl.NumberFormat('en-US').format(amount)
|
|
// Add some excitement for larger amounts
|
|
if (amount >= 1000000) return formatted + ' sats 💎'
|
|
if (amount >= 100000) return formatted + ' sats 🚀'
|
|
if (amount >= 10000) return formatted + ' sats ⚡'
|
|
return formatted + ' sats'
|
|
},
|
|
|
|
async loadDashboardData() {
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
'/satmachineclient/api/v1/dashboard/summary',
|
|
this.g.user.wallets[0].inkey
|
|
)
|
|
this.dashboardData = data
|
|
} catch (error) {
|
|
console.error('Error loading dashboard data:', error)
|
|
this.error = 'Failed to load dashboard data'
|
|
}
|
|
},
|
|
|
|
async loadTransactions() {
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
'/satmachineclient/api/v1/dashboard/transactions?limit=50',
|
|
this.g.user.wallets[0].inkey
|
|
)
|
|
// Sort by most recent first and store
|
|
this.transactions = data.sort((a, b) => {
|
|
const dateA = new Date(a.transaction_time || a.created_at)
|
|
const dateB = new Date(b.transaction_time || b.created_at)
|
|
return dateB - dateA // Most recent first
|
|
})
|
|
} catch (error) {
|
|
console.error('Error loading transactions:', error)
|
|
this.$q.notify({
|
|
type: 'negative',
|
|
message: 'Failed to load transactions',
|
|
position: 'top'
|
|
})
|
|
}
|
|
},
|
|
|
|
async refreshAllData() {
|
|
try {
|
|
this.loading = true
|
|
await Promise.all([
|
|
this.loadDashboardData(),
|
|
this.loadTransactions()
|
|
])
|
|
this.$q.notify({
|
|
type: 'positive',
|
|
message: 'Dashboard refreshed!',
|
|
icon: 'refresh',
|
|
position: 'top'
|
|
})
|
|
} catch (error) {
|
|
console.error('Error refreshing data:', error)
|
|
this.$q.notify({
|
|
type: 'negative',
|
|
message: 'Failed to refresh data',
|
|
position: 'top'
|
|
})
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
getNextMilestone() {
|
|
if (!this.dashboardData) return { target: 100000, name: '100k sats' }
|
|
const sats = this.dashboardData.total_sats_accumulated
|
|
|
|
if (sats < 10000) return { target: 10000, name: '10k sats' }
|
|
if (sats < 100000) return { target: 100000, name: '100k sats' }
|
|
if (sats < 500000) return { target: 500000, name: '500k sats' }
|
|
if (sats < 1000000) return { target: 1000000, name: '1M sats' }
|
|
if (sats < 2100000) return { target: 2100000, name: '2.1M sats' }
|
|
return { target: 21000000, name: '21M sats' }
|
|
},
|
|
|
|
getMilestoneProgress() {
|
|
if (!this.dashboardData) return 0
|
|
const sats = this.dashboardData.total_sats_accumulated
|
|
const milestone = this.getNextMilestone()
|
|
|
|
// Show total progress toward the next milestone (from 0)
|
|
const progress = (sats / milestone.target) * 100
|
|
return Math.min(Math.max(progress, 0), 100)
|
|
}
|
|
},
|
|
|
|
async created() {
|
|
try {
|
|
this.loading = true
|
|
await Promise.all([
|
|
this.loadDashboardData(),
|
|
this.loadTransactions()
|
|
])
|
|
} catch (error) {
|
|
console.error('Error initializing dashboard:', error)
|
|
this.error = 'Failed to initialize dashboard'
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
hasData() {
|
|
return this.dashboardData && !this.loading
|
|
}
|
|
}
|
|
})
|