-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(mpesa): Add dashboard components
Co-authored-by: Joseph Mania <[email protected]>
- Loading branch information
1 parent
aa1a0aa
commit 7e38127
Showing
17 changed files
with
1,870 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -480,6 +480,7 @@ | |
"Vetur", | ||
"Mpesa", | ||
"msisdn", | ||
"stkpush" | ||
"stkpush", | ||
"Pesa" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
<template> | ||
<Dialog :options="{ title: 'Add Currency Exchange', size: 'lg' }"> | ||
<template #body-content> | ||
<div class="grid grid-cols-2 gap-4"> | ||
<FormControl | ||
label="From Currency" | ||
v-model="fromCurrency" | ||
type="autocomplete" | ||
variant="subtle" | ||
:disabled="false" | ||
:options="currencySymbols" | ||
name="from_currency" | ||
class="mb-5" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="To Currency" | ||
v-model="toCurrency" | ||
name="to_currency" | ||
type="autocomplete" | ||
variant="subtle" | ||
:disabled="false" | ||
:options="currencySymbols" | ||
class="mb-5" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="Exchange Rate" | ||
v-model="exchangeRate" | ||
name="exchange_rate" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="number" | ||
required | ||
/> | ||
|
||
<DatePicker | ||
v-model="date" | ||
variant="subtle" | ||
name="date" | ||
placeholder="Placeholder" | ||
:disabled="false" | ||
label="Date" | ||
/> | ||
</div> | ||
|
||
<div class="mt-4 flex w-full items-center justify-center"> | ||
<Button | ||
@click="saveExchangeRate" | ||
class="justify-center w-full font-bold" | ||
variant="solid" | ||
type="primary" | ||
>Add Currency Exchange</Button | ||
> | ||
</div> | ||
</template> | ||
<ErrorMessage class="mt-2" :message="ErrorMessage" /> | ||
</Dialog> | ||
</template> | ||
|
||
<script> | ||
import { toast } from 'vue-sonner'; | ||
import { frappeRequest } from 'frappe-ui'; | ||
import { DashboardError } from '../../utils/error'; | ||
import FormControl from 'frappe-ui/src/components/FormControl.vue'; | ||
import DatePicker from 'frappe-ui/src/components/DatePicker.vue'; | ||
import ErrorMessage from 'frappe-ui/src/components/ErrorMessage.vue'; | ||
export default { | ||
name: 'AddExchangeRate', | ||
components: { DatePicker }, | ||
data() { | ||
return { | ||
fromCurrency: '', | ||
toCurrency: '', | ||
date: '', | ||
exchangeRate: '', | ||
currencySymbols: [], | ||
}; | ||
}, | ||
resources: { | ||
addCurrencyExchange() { | ||
return { | ||
url: 'press.api.regional_payments.mpesa.utils.create_exchange_rate', | ||
params: { | ||
from_currency: this.fromCurrency, | ||
to_currency: this.toCurrency, | ||
exchange_rate: this.exchangeRate, | ||
date: this.date, | ||
}, | ||
validate() { | ||
if ( | ||
!this.fromCurrency || | ||
!this.toCurrency || | ||
!this.exchangeRate || | ||
!this.date | ||
) { | ||
toast.error('All fields are required'); | ||
return false; | ||
} | ||
}, | ||
async onSuccess() { | ||
if (data) { | ||
toast.success('Currency Exchange Added Successfully'); | ||
this.$emit('close'); | ||
} else { | ||
toast.error('Failed to add currency exchange'); | ||
} | ||
}, | ||
}; | ||
}, | ||
}, | ||
methods: { | ||
async saveExchangeRate() { | ||
try { | ||
const response = await this.$resources.addCurrencyExchange.submit(); | ||
if (response) { | ||
this.$toast.success('Currency Exchange Added Successfully'); | ||
this.fromCurrency = ''; | ||
this.toCurrency = ''; | ||
this.exchangeRate = ''; | ||
this.date = ''; | ||
} | ||
this.$emit('closeDialog'); | ||
} catch (error) { | ||
console.log(error); | ||
this.$toast.error(`Error adding currency exchange: ${error.message}`); | ||
} | ||
}, | ||
async fetchCurrencySymbols() { | ||
try { | ||
const response = await frappeRequest({ | ||
url: '/api/method/press.api.regional_payments.mpesa.utils.fetch_currencies', | ||
method: 'GET', | ||
}); | ||
if (Array.isArray(response)) { | ||
this.currencySymbols = response; | ||
} else { | ||
this.ErrorMessage = 'No currency symbols found'; | ||
} | ||
} catch (error) { | ||
this.ErrorMessage = `Error fetching currency symbols: ${error.message}`; | ||
} | ||
}, | ||
}, | ||
mounted() { | ||
this.fetchCurrencySymbols(); | ||
}, | ||
}; | ||
</script> |
179 changes: 179 additions & 0 deletions
179
dashboard/src2/components/billing/mpesa/AddMpesaCredentials.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
<template> | ||
<Dialog :options="{ title: 'Add M-Pesa Credentials', size: 'lg' }"> | ||
<template #body-content> | ||
<div class="grid grid-cols-2 gap-4"> | ||
<FormControl | ||
label="Payment Gatway Name" | ||
v-model="paymentGatewayName" | ||
name="consumer_key" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="text" | ||
placeholder="Enter Mpesa setting Name" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="Consumer Key" | ||
v-model="consumerKey" | ||
name="consumer_key" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="text" | ||
placeholder="Enter Consumer Key" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="Consumer Secret" | ||
v-model="consumerSecret" | ||
name="consumer_secret" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="text" | ||
placeholder="Enter Consumer Secret" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="Pass Key" | ||
v-model="passKey" | ||
name="pass_key" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="text" | ||
placeholder="Enter Pass Key" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="Short Code" | ||
v-model="shortCode" | ||
name="short_code" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="text" | ||
placeholder="Enter Short Code" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="Initiator Name" | ||
v-model="initiatorName" | ||
name="initiator_name" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="text" | ||
placeholder="Enter Initiator Name" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="Security Credential" | ||
v-model="securityCredential" | ||
name="security_credential" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="text" | ||
placeholder="Enter Security Credential" | ||
required | ||
/> | ||
|
||
<FormControl | ||
label="Till Number" | ||
v-model="tillNumber" | ||
name="till_number" | ||
autocomplete="off" | ||
class="mb-5" | ||
type="text" | ||
placeholder="Enter Till Number" | ||
required | ||
/> | ||
|
||
<div class="flex items-center"> | ||
<input v-model="sandBox" type="checkbox" class="mr-2" /> | ||
<label class="text-sm font-medium text-gray-700">Sandbox Mode</label> | ||
</div> | ||
</div> | ||
|
||
<div class="mt-4 flex w-full bg-red-300 items-center justify-center"> | ||
<Button | ||
@click="saveMpesaCredentials" | ||
variant="solid" | ||
class="justify-center w-full font-bold" | ||
>Save</Button | ||
> | ||
</div> | ||
</template> | ||
</Dialog> | ||
</template> | ||
|
||
<script> | ||
import { toast } from 'vue-sonner'; | ||
import { DashboardError } from '../../../utils/error'; | ||
import { ErrorMessage } from 'frappe-ui'; | ||
export default { | ||
name: 'AddMpesaCredentials', | ||
data() { | ||
return { | ||
consumerKey: '', | ||
paymentGatewayName: '', | ||
consumerSecret: '', | ||
passKey: '', | ||
shortCode: '', | ||
initiatorName: '', | ||
securityCredential: '', | ||
tillNumber: '', | ||
sandBox: false, | ||
}; | ||
}, | ||
resources: { | ||
createMpesaSetup() { | ||
return { | ||
url: 'press.api.regional_payments.mpesa.utils.create_mpesa_setup', | ||
params: { | ||
payment_gateway_name: this.paymentGatewayName, | ||
consumer_key: this.consumerKey, | ||
consumer_secret: this.consumerSecret, | ||
pass_key: this.passKey, | ||
short_code: this.shortCode, | ||
initiator_name: this.initiatorName, | ||
security_credential: this.securityCredential, | ||
till_number: this.tillNumber, | ||
sandbox: this.sandBox, | ||
}, | ||
validate() { | ||
if ( | ||
!this.paymentGatewayName || | ||
!this.consumerKey || | ||
!this.consumerSecret || | ||
!this.passKey || | ||
!this.shortCode || | ||
!this.initiatorName || | ||
!this.securityCredential | ||
) { | ||
return 'All fields are required'; | ||
} | ||
}, | ||
async onSuccess(data) { | ||
if (data) { | ||
toast.success('M-Pesa credentials saved', data); | ||
} else { | ||
toast.error('Error saving M-Pesa credentials'); | ||
} | ||
}, | ||
}; | ||
}, | ||
}, | ||
methods: { | ||
async saveMpesaCredentials() { | ||
try { | ||
const response = await this.$resources.createMpesaSetup.submit(); | ||
this.$emit('closeDialog'); | ||
} catch (error) { | ||
this.$toast.error(`Error saving M-Pesa credentials: ${error.message}`); | ||
} | ||
}, | ||
}, | ||
}; | ||
</script> |
Oops, something went wrong.