219 lines
5.8 KiB
Vue
219 lines
5.8 KiB
Vue
<script setup>
|
|
import { usePageTitle } from '../composables/Core/usePageTitle';
|
|
usePageTitle('Transfer My Credit');
|
|
|
|
import { ref, onMounted } from 'vue'
|
|
import axios from 'axios'
|
|
import { useNavigate } from '../composables/Core/useNavigate'
|
|
import { useModal } from '../composables/Core/useModal'
|
|
import { useAuth } from '../composables/Core/useAuth'
|
|
|
|
const { navigate } = useNavigate()
|
|
import BackButton from '../Components/Core/BackButton.vue'
|
|
const modal = useModal()
|
|
const { user, userStore } = useAuth()
|
|
|
|
// Form state
|
|
const transferAmount = ref('')
|
|
const targetUser = ref('')
|
|
|
|
// Data lists
|
|
const userList = ref([])
|
|
|
|
// Loading state
|
|
const isLoading = ref(false)
|
|
|
|
// Initialize component
|
|
onMounted(() => {
|
|
document.title = 'Transfer My Credit'
|
|
|
|
// Get target user from query params
|
|
const urlParams = new URLSearchParams(window.location.search)
|
|
targetUser.value = urlParams.get('target') || ''
|
|
|
|
if (!targetUser.value) {
|
|
modal.open({
|
|
title: 'Error',
|
|
body: 'Target user not found. Please select a recipient.',
|
|
footer: null
|
|
})
|
|
return
|
|
}
|
|
})
|
|
|
|
// Load users (for target selection)
|
|
const loadUsers = async () => {
|
|
try {
|
|
const response = await axios.get('/admin/users/list')
|
|
if (response.data && response.data.success && Array.isArray(response.data.users)) {
|
|
userList.value = response.data.users.map(user => ({
|
|
value: user.id,
|
|
label: `${user.name} (${user.mobile_number}) [${user.username}] ${user.fullname ?? ''}`
|
|
}))
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading users:', error)
|
|
}
|
|
}
|
|
|
|
// Validate form
|
|
const validateForm = () => {
|
|
if (!transferAmount.value || parseFloat(transferAmount.value) <= 0) {
|
|
modal.open({ title: 'Error', body: 'Please enter a valid amount', footer: null })
|
|
return false
|
|
}
|
|
|
|
const currentBalance = userStore.balance || 0
|
|
if (parseFloat(transferAmount.value) > currentBalance) {
|
|
modal.open({ title: 'Error', body: 'Insufficient balance', footer: null })
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// Show confirmation modal
|
|
const showConfirmationModal = () => {
|
|
if (!validateForm()) return
|
|
|
|
const targetUserName = userList.value.find(u => u.value == targetUser.value)?.label || targetUser.value
|
|
|
|
modal.yesNoModal({
|
|
title: 'Transfer Credit?',
|
|
body: `You are sending <strong>${(parseFloat(transferAmount.value) || 0).toLocaleString()}</strong> credits from your account to <strong>${targetUserName}</strong>?`,
|
|
onYes: transferCredit,
|
|
yesText: 'Continue',
|
|
noText: 'Cancel'
|
|
})
|
|
}
|
|
|
|
// Transfer credit
|
|
const transferCredit = async () => {
|
|
try {
|
|
isLoading.value = true
|
|
|
|
const response = await axios.post('/user/sendmycredit', {
|
|
amount: parseFloat(transferAmount.value),
|
|
target_user: targetUser.value
|
|
})
|
|
|
|
if (response.data === true || (response.data && response.data.success)) {
|
|
showSuccessModal()
|
|
} else {
|
|
showErrorModal(response.data?.message || 'Transfer failed')
|
|
}
|
|
} catch (error) {
|
|
console.error('Error transferring credit:', error)
|
|
showErrorModal(error.response?.data?.message || 'Failed to transfer credit. Please try again.')
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
// Show success modal
|
|
const showSuccessModal = () => {
|
|
modal.continueCancelModal({
|
|
title: 'Success',
|
|
body: 'Transfer has been successful.',
|
|
onContinue: () => {
|
|
navigate({ page: 'AccountSettings' })
|
|
},
|
|
continueText: 'OK',
|
|
continueClass: 'btn btn-primary',
|
|
showCancel: false
|
|
})
|
|
}
|
|
|
|
// Show error modal
|
|
const showErrorModal = (message) => {
|
|
modal.open({
|
|
title: 'Failed',
|
|
body: message,
|
|
footer: null
|
|
})
|
|
}
|
|
|
|
// Cancel and go back
|
|
const cancel = () => {
|
|
navigate({ page: 'AccountSettings' })
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="transfer-credit-page pb-5">
|
|
<br><br>
|
|
|
|
<div class="tf-container">
|
|
<h2 class="fw_6 text-center mb-4">Transfer My Credit</h2>
|
|
|
|
<!-- Back Button -->
|
|
<div class="text-start mb-4">
|
|
<BackButton to="AccountSettings" text="Cancel" />
|
|
</div>
|
|
|
|
<!-- Card for Transfer Form -->
|
|
<div class="card shadow-sm">
|
|
<div class="card-header ui-sortable-handle" style="cursor: move;">
|
|
<div class="row">
|
|
<div class="col">
|
|
<h4 class="card-title">Transfer Credit</h4>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body" id="credit-amount-request-form">
|
|
<div class="row g-3">
|
|
<!-- Amount Input -->
|
|
<div class="col-md-6">
|
|
<input
|
|
type="number"
|
|
id="transfer-credit-amount-field"
|
|
class="form-control"
|
|
placeholder="Amount to Transfer"
|
|
step="0.01"
|
|
min="0"
|
|
v-model.number="transferAmount"
|
|
:disabled="isLoading"
|
|
>
|
|
</div>
|
|
|
|
<!-- Transfer Button -->
|
|
<div class="col-md-6">
|
|
<button
|
|
id="Transfer-credit-initial-button"
|
|
class="btn btn-primary w-100 py-2"
|
|
@click="showConfirmationModal"
|
|
:disabled="isLoading"
|
|
>
|
|
Transfer Credit
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Balance Info -->
|
|
<div class="card shadow-sm mt-3">
|
|
<div class="card-body text-center">
|
|
<h5 class="card-title">Your Current Balance</h5>
|
|
<p class="fw_6 fs-4 mb-0" v-if="userStore.balance !== null">
|
|
{{ (userStore.balance || 0).toLocaleString() }}
|
|
</p>
|
|
<p class="text-muted" v-else>Loading balance...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.card {
|
|
border-radius: 12px;
|
|
}
|
|
.card-header {
|
|
background-color: #f8f9fa;
|
|
}
|
|
.btn-primary:hover {
|
|
transform: translateY(-1px);
|
|
}
|
|
</style> |