Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions frontend/kubecloud/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ onMounted(async () => {
return
}
userStore.initializeAuth()
if(userStore.isLoggedIn){
await userStore.loadUser()
}
await notificationStore.loadNotifications()
} catch (error) {
console.error('Failed to initialize application:', error)
Expand Down
10 changes: 5 additions & 5 deletions frontend/kubecloud/src/components/AdminSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const adminNavItems = [
{ key: 'vouchers', title: 'Vouchers', icon: 'mdi-ticket-percent' },
{ key: 'system', title: 'System', icon: 'mdi-cog' },
{ key: 'invoices', title: 'Invoices', icon: 'mdi-file-document-outline' },
{ key: 'payments', title: 'Payments', icon: 'mdi-clock-outline' },
{ key: 'transfers', title: 'Transfers', icon: 'mdi-swap-horizontal' },
{ key: 'emails', title: 'Emails', icon: 'mdi-email-outline' },
]

Expand Down Expand Up @@ -140,18 +140,18 @@ const adminNavItems = [
.admin-sidebar-card {
padding: 1rem;
}

.sidebar-header {
margin-bottom: 1rem;
padding-bottom: 0.75rem;
}

.sidebar-title {
font-size: var(--font-size-base, 1rem);
}

.sidebar-subtitle {
font-size: var(--font-size-xs, 0.75rem);
}
}
</style>
</style>
36 changes: 24 additions & 12 deletions frontend/kubecloud/src/components/AdminUsersTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,40 @@
{ title: 'ID', key: 'id', width: '80px' },
{ title: 'Name', key: 'username' },
{ title: 'Email', key: 'email' },
{ title: 'Balance', key: 'balance' },
{ title: 'Balance (USD)', key: 'balance_in_usd' },
{ title: 'Balance (TFT)', key: 'balance_in_tft' },
{ title: 'Admin', key: 'admin' },
{ title: 'Actions', key: 'actions', sortable: false, width: '160px' }
]"
:items="users"
:items-per-page="pageSize"
:page="currentPage"
:sort-by="[{ key: 'id', order: 'asc' }]"
@update:page="$emit('update:currentPage', $event)"
class="admin-table"
density="comfortable"
>
<template #item.balance="{ item }">
${{ item.balance.toFixed(2) }}
<template #item.balance_in_usd="{ item }">
${{ +calculateNetBalance(item).toFixed(2) }}
</template>
<template #item.balance_in_tft="{ item }">
{{ +item.balance_in_tft.toFixed(2) }}
</template>
<template #item.admin="{ item }">
<v-checkbox v-if="item.admin" style=" display: flex; align-items: center;" :model-value="item.admin" disabled></v-checkbox>
</template>
<template #item.actions="{ item }">
<div style="display: flex; gap: var(--space-4); align-items: center;">
<v-btn size="small" variant="outlined" class="action-btn" :disabled="!item.verified" @click="$emit('creditUser', item)">
<v-icon icon="mdi-cash-plus" size="16" class="mr-1"></v-icon>
Credit Balance
</v-btn>
<v-btn size="small" variant="outlined" class="action-btn" @click="$emit('deleteUser', item.id)">
<v-icon icon="mdi-delete" size="16" class="mr-1"></v-icon>
Remove
</v-btn>
<v-tooltip location="bottom" text="Credit user">
<template #activator="{ props }">
<v-btn v-bind="props" size="small" icon="mdi-cash-plus" :disabled="!item.verified" @click="$emit('creditUser', item)"></v-btn>
</template>
</v-tooltip>
<v-tooltip location="bottom" text="Delete user">
<template #activator="{ props }">
<v-btn v-bind="props" size="small" icon="mdi-delete" @click="$emit('deleteUser', item.id)"></v-btn>
</template>
</v-tooltip>
</div>
</template>
</v-data-table>
Expand All @@ -52,8 +63,9 @@

<script setup lang="ts">
import { ref, watch } from 'vue'
import type { User } from '../stores/user'
import type { User } from '../types/user'

import { calculateNetBalance } from '../utils/dateUtils'
const props = defineProps({
users: Array as () => User[],
searchQuery: String,
Expand Down
5 changes: 0 additions & 5 deletions frontend/kubecloud/src/components/DashboardSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,6 @@ const navigationItems = [
title: 'Billing History',
icon: 'mdi-receipt'
},
{
key: 'payments',
title: 'Payments',
icon: 'mdi-clock-outline'
},
{
key: 'vouchers',
title: 'Vouchers',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,42 @@
<div class="dashboard-card-header">
<div class="dashboard-card-title-section">
<div class="dashboard-card-title-content">
<h3 class="dashboard-card-title">Payments</h3>
<p class="dashboard-card-subtitle">View user payment records</p>
<h3 class="dashboard-card-title">Transactions</h3>
<p class="dashboard-card-subtitle">View transactions records</p>
</div>
</div>
</div>
<PendingRecordsTable
:pendingRecords="pendingRecords"
:showUserID="true"
<TransferRecordsTable
:transferRecords="transferRecords"
:loading="loading"
/>
</div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { type PendingRecord } from '../../utils/userService'
import PendingRecordsTable from './PendingRecordsTable.vue'
import { type TransferRecord } from '../../utils/adminService'
import TransferRecordsTable from './TransferRecordsTable.vue'
import { useNotificationStore } from '../../stores/notifications'
import { adminService } from '../../utils/adminService'

const pendingRecords = ref<PendingRecord[]>([])
const transferRecords = ref<TransferRecord[]>([])
const notificationStore = useNotificationStore()

onMounted(async () => {
await loadPendingRecords()
await loadTransferRecords()
})

const loading = ref(false)

async function loadPendingRecords() {
async function loadTransferRecords() {
loading.value = true
try {
const response = await adminService.listPendingRecords()
pendingRecords.value = response || []
const response = await adminService.listTransferRecords()
transferRecords.value = response || []
} catch (error) {
console.error('Failed to load payments:', error)
notificationStore.error('Error', 'Failed to load payments')
console.error('Failed to load transfer records:', error)
notificationStore.error('Error', 'Failed to load transfer records')
} finally {
loading.value = false
}
Expand Down
3 changes: 0 additions & 3 deletions frontend/kubecloud/src/components/dashboard/OverviewCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,9 @@ const props = defineProps<Props>()
const router = useRouter()
const userStore = useUserStore()
const netBalance = ref(userStore.netBalance)
const pendingBalance = ref(userStore.pendingBalance)

watchEffect(() => {
netBalance.value = userStore.netBalance
pendingBalance.value = userStore.pendingBalance
})

// Computed data for stats
Expand All @@ -83,7 +81,6 @@ const statsData = computed(() => {
{
icon: 'mdi-currency-usd',
value: `$${netBalance.value.toFixed(2)}`,
subvalue: pendingBalance.value > 0 ? `+$${pendingBalance.value.toFixed(2)} pending` : '',
label: 'Balance'
},
{
Expand Down
4 changes: 0 additions & 4 deletions frontend/kubecloud/src/components/dashboard/PaymentCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
<span>Current Balance:</span>
<span class="balance-value">${{ userStore.netBalance.toFixed(2) }}</span>
</div>
<div class="balance-row" v-if="userStore.pendingBalance > 0">
<span class="pending-balance-text">Pending Balance:</span>
<span class="pending-balance-value">${{ userStore.pendingBalance.toFixed(2) }}</span>
</div>
</div>
<div class="amount-row">
<span>Amount:</span>
Expand Down
101 changes: 0 additions & 101 deletions frontend/kubecloud/src/components/dashboard/PendingRecordsTable.vue

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<div class="profile-row">
<div class="profile-col">
<label class="profile-label">Balance</label>
<v-text-field :model-value="`$${userStore.netBalance.toFixed(2)}${userStore.pendingBalance > 0 ? ` (+$${userStore.pendingBalance.toFixed(2)} pending)` : ''}`" variant="outlined" class="profile-field compact" color="accent" bg-color="transparent" hide-details="auto" disabled density="compact" />
<v-text-field :model-value="`$${userStore.netBalance.toFixed(2)}`" variant="outlined" class="profile-field compact" color="accent" bg-color="transparent" hide-details="auto" disabled density="compact" />
</div>
<div class="profile-col">
<label class="profile-label">Verified</label>
Expand Down
Loading