NT Pay app. Money send on distance, transaction log! (#70108)

* base

* reasons

* GetToken proc, with a many remarks

* Add a way to change reason in transfer_money proc. Add a reasons.

* Reason to use the app. Commission. Standard application.

* Apply suggestions from code review - Tralezab

Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com>

* Tralezab & jlsnow301 advices. New format(everywhere)

* Nanotrasen

* Refactor TGUI(not me:( ). Fix useless capitalize

* Update code/modules/economy/account.dm

* Trans transforms in transaction

* coMmission. little autodoc mistalke. Translation != Transaction

* oops

* Merge Conflict

* ...

* back feats

* mistakes bye!

* ну да

Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com>
This commit is contained in:
Yaroslav Nurkov
2022-10-05 18:25:38 -04:00
committed by GitHub
co-authored by tralezab
parent 92bdb50232
commit 04ca99d7e9
27 changed files with 355 additions and 42 deletions
+1 -1
View File
@@ -156,7 +156,7 @@
to_chat(user, span_warning("ID Card lacks funds. Aborting."))
user.balloon_alert(user, "Cost: [total_cost] credits.")
return FALSE
target_acc.transfer_money(idcard.registered_account, total_cost)
target_acc.transfer_money(idcard.registered_account, total_cost, "Nanotrasen: Usage of Corporate Machinery")
log_econ("[total_cost] credits were spent on [parent] by [user] via [idcard.registered_account.account_holder]'s card.")
idcard.registered_account.bank_card_talk("[total_cost] credits deducted from your account.")
playsound(src, 'sound/effects/cashregister.ogg', 20, TRUE)
+1 -1
View File
@@ -90,7 +90,7 @@
// And of course, the cut is removed from what cargo gets. (But not below zero, just in case)
overall_item_price = max(0, overall_item_price - payee_cut)
payee.adjust_money(payee_cut)
payee.adjust_money(payee_cut, "Pricetag: [capitalize(source)] Sale")
payee.bank_card_talk("Sale of [source] recorded. [payee_cut] credits added to account.")
// Update the report with the modified final price
@@ -263,7 +263,7 @@
var/holochip_amount = id_card.registered_account.account_balance
new /obj/item/holochip(wallet, holochip_amount)
id_card.registered_account.adjust_money(-holochip_amount)
id_card.registered_account.adjust_money(-holochip_amount, "System: Withdrawal")
new /obj/effect/spawner/random/entertainment/wallet_storage(wallet)
@@ -83,7 +83,7 @@
say("No bank account detected!")
return
var/final_cost = get_total_cost()
if(!chef_card.registered_account.adjust_money(-final_cost))
if(!chef_card.registered_account.adjust_money(-final_cost, "Chef Order: Purchase"))
say("Sorry, but you do not have enough money.")
return
say("Thank you for your purchase! It will arrive on the next cargo shuttle!")
@@ -106,7 +106,7 @@
return
var/final_cost = get_total_cost()
final_cost *= 2
if(!chef_card.registered_account.adjust_money(-final_cost))
if(!chef_card.registered_account.adjust_money(-final_cost, "Chef Order: Purchase"))
say("Sorry, but you do not have enough money. Remember, Express upcharges the cost!")
return
say("Thank you for your purchase! Please note: The charge of this purchase and machine cooldown has been doubled!")
@@ -792,7 +792,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
if(!current_user.has_money(active_request.value) || (current_user.account_holder != active_request.owner))
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
return TRUE
payment_target.transfer_money(current_user, active_request.value)
payment_target.transfer_money(current_user, active_request.value, "Bounty Request")
say("Paid out [active_request.value] credits.")
GLOB.request_list.Remove(active_request)
qdel(active_request)
+2 -2
View File
@@ -205,7 +205,7 @@
var/payout = potential_payout
my_card.registered_account.transfer_money(player_id.registered_account, bet_amount)
my_card.registered_account.transfer_money(player_id.registered_account, bet_amount, "Roulette: Bet")
playing = TRUE
update_appearance()
@@ -262,7 +262,7 @@
var/remaining_payout = payout
my_card.registered_account.adjust_money(-payout)
my_card.registered_account.adjust_money(-payout, "Roulette: Payout")
for(var/coin_type in coin_values) //Loop through all coins from most valuable to least valuable. Try to give as much of that coin (the iterable) as possible until you can't anymore, then move to the next.
var/value = coin_values[coin_type] //Change this to use initial value once we change to mat datum coins.
+16 -6
View File
@@ -102,6 +102,12 @@
/// Boolean value. If TRUE, the [Intern] tag gets prepended to this ID card when the label is updated.
var/is_intern = FALSE
///Way to use NT pay. Or how to save money. 1 - 100%, 0.05 - 5%
var/commission = 0.05
///Payment under >99 credits withdraw. (this + 1 = min value to withdraw)
var/commission_minimal = 5
/obj/item/card/id/Initialize(mapload)
. = ..()
@@ -580,7 +586,7 @@
if(!cash_money)
to_chat(user, span_warning("[money] doesn't seem to be worth anything!"))
return
registered_account.adjust_money(cash_money)
registered_account.adjust_money(cash_money, "System: Deposit")
SSblackbox.record_feedback("amount", "credits_inserted", cash_money)
log_econ("[cash_money] credits were inserted into [src] owned by [src.registered_name]")
if(physical_currency)
@@ -612,7 +618,7 @@
total += physical_money.get_item_credit_value()
CHECK_TICK
registered_account.adjust_money(total)
registered_account.adjust_money(total, "System: Deposit")
SSblackbox.record_feedback("amount", "credits_inserted", total)
log_econ("[total] credits were inserted into [src] owned by [src.registered_name]")
QDEL_LIST(money)
@@ -665,15 +671,19 @@
if(loc != user)
to_chat(user, span_warning("You must be holding the ID to continue!"))
return
var/amount_to_remove = tgui_input_number(user, "How much do you want to withdraw? (Max: [registered_account.account_balance] cr)", "Withdraw Funds", max_value = registered_account.account_balance)
if(registered_account.account_balance < (commission_minimal + 1) )
to_chat(user, span_warning("You must be holding the ID to continue!"))
return
var/amount_to_remove = tgui_input_number(user, "How much do you want to withdraw? (Max: [registered_account.account_balance] cr)(Commission is [commission_minimal] credits. From 100 credits is [commission * 100]% with rounding.)", "Withdraw Funds", max_value = registered_account.account_balance, min_value = 6)
if(!amount_to_remove || QDELETED(user) || QDELETED(src) || issilicon(user) || loc != user)
return
if(!alt_click_can_use_id(user))
return
if(registered_account.adjust_money(-amount_to_remove))
var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove)
if(registered_account.adjust_money(-amount_to_remove, "System: Withdrawal"))
var/commission_amount = amount_to_remove < 100 ? commission_minimal : round(amount_to_remove * commission)
var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove - commission_amount)
user.put_in_hands(holochip)
to_chat(user, span_notice("You withdraw [amount_to_remove] credits into a holochip."))
to_chat(user, span_notice("You withdraw [amount_to_remove - commission_amount] credits into a holochip. Commission was [commission_amount] credits"))
SSblackbox.record_feedback("amount", "credits_removed", amount_to_remove)
log_econ("[amount_to_remove] credits were removed from [src] owned by [src.registered_name]")
return
+1 -1
View File
@@ -200,7 +200,7 @@
var/amount = B.account_balance * percentage_lost
var/datum/bank_account/account = bogdanoff?.get_bank_account()
if (account) // get_bank_account() may return FALSE
account.transfer_money(B, amount)
account.transfer_money(B, amount, "?VIVA¿: !LA CRABBE¡")
B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src)].")
addtimer(CALLBACK(src, .proc/dump), 150) //Drain every 15 seconds
+2 -2
View File
@@ -471,9 +471,9 @@
to_chat(usr, span_notice("You do not possess the funds to purchase this."))
return TRUE
else
account.adjust_money(-sale_price)
account.adjust_money(-sale_price, "Display Case: [capitalize(showpiece)]")
if(payments_acc)
payments_acc.adjust_money(sale_price)
payments_acc.adjust_money(sale_price, "Display Case: [capitalize(showpiece)]")
usr.put_in_hands(showpiece)
to_chat(usr, span_notice("You purchase [showpiece] for [sale_price] credits."))
playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE)
+1 -1
View File
@@ -214,7 +214,7 @@
return
if(sniped_amount != painting_metadata.credit_value)
return
if(!account.adjust_money(-offer_amount))
if(!account.adjust_money(-offer_amount, "Painting: Patron of [painting_metadata.title]"))
to_chat(user, span_warning("Transaction failure. Please try again."))
return
painting_metadata.patron_ckey = user.ckey
+1 -1
View File
@@ -47,7 +47,7 @@
return FALSE
if(I.buy(uplink, user, method))
uplink.current_user.adjust_money(-price)
uplink.current_user.adjust_money(-price, "Other: Third Party Transaction")
if(ismob(user))
var/mob/m_user = user
m_user.playsound_local(get_turf(m_user), 'sound/machines/twobeep_high.ogg', 50, TRUE)
+44 -5
View File
@@ -25,6 +25,10 @@
var/replaceable = FALSE
///Cooldown timer on replacing a civilain bounty. Bounties can only be replaced once every 5 minutes.
COOLDOWN_DECLARE(bounty_timer)
///A special semi-tandom token for tranfering money from NT pay app
var/pay_token
///List with a transaction history for NT pay app
var/list/transaction_history = list()
/datum/bank_account/New(newname, job, modifier = 1, player_account = TRUE)
account_holder = newname
@@ -32,6 +36,7 @@
payday_modifier = modifier
add_to_accounts = player_account
setup_unique_account_id()
pay_token = uppertext("[copytext(newname, 1, 2)][copytext(newname, -1)]-[random_capital_letter()]-[rand(1111,9999)]")
/datum/bank_account/Destroy()
if(add_to_accounts)
@@ -59,6 +64,7 @@
/datum/bank_account/vv_edit_var(var_name, var_value) // just so you don't have to do it manually
var/old_id = account_id
var/old_balance = account_balance
. = ..()
switch(var_name)
if(NAMEOF(src, account_id))
@@ -70,6 +76,8 @@
setup_unique_account_id()
else
SSeconomy.bank_accounts_by_id -= "[account_id]"
if(NAMEOF(src, account_balance))
add_log_to_history(var_value - old_balance, "Nanotrasen: Moderator Action")
/**
* Sets the bank_account to behave as though a CRAB-17 event is happening.
@@ -100,10 +108,13 @@
* Adjusts the balance of a bank_account as well as sanitizes the numerical input.
* Arguments:
* * amount - the quantity of credits that will be written off if the value is negative, or added if it is positive.
* * reason - the reason for the appearance or loss of money
*/
/datum/bank_account/proc/adjust_money(amount)
/datum/bank_account/proc/adjust_money(amount, reason)
if((amount < 0 && has_money(-amount)) || amount > 0)
_adjust_money(amount)
if(reason)
add_log_to_history(amount, reason)
return TRUE
return FALSE
@@ -112,13 +123,25 @@
* Arguments:
* * datum/bank_account/from - The bank account that is sending the credits to this bank_account datum.
* * amount - the quantity of credits that are being moved between bank_account datums.
* * transfer_reason - override for adjust_money reason. Use if no default reason(Transfer to/from Name Surname).
*/
/datum/bank_account/proc/transfer_money(datum/bank_account/from, amount)
/datum/bank_account/proc/transfer_money(datum/bank_account/from, amount, transfer_reason)
if(from.has_money(amount))
adjust_money(amount)
var/reason_to = "Transfer: From [from.account_holder]"
var/reason_from = "Transfer: To [account_holder]"
if(istype(from, /datum/bank_account/department))
reason_to = "Nanotrasen: Salary"
reason_from = ""
if(transfer_reason)
reason_to = istype(src, /datum/bank_account/department) ? "" : transfer_reason
reason_from = transfer_reason
adjust_money(amount, reason_to)
from.adjust_money(-amount, reason_from)
SSblackbox.record_feedback("amount", "credits_transferred", amount)
log_econ("[amount] credits were transferred from [from.account_holder]'s account to [src.account_holder]")
from.adjust_money(-amount)
return TRUE
return FALSE
@@ -136,7 +159,7 @@
if(amount_of_paychecks == 1)
money_to_transfer = clamp(money_to_transfer, 0, PAYCHECK_CREW) //We want to limit single, passive paychecks to regular crew income.
if(free)
adjust_money(money_to_transfer)
adjust_money(money_to_transfer, "Nanotrasen: Shift Payment")
SSblackbox.record_feedback("amount", "free_income", money_to_transfer)
SSeconomy.station_target += money_to_transfer
log_econ("[money_to_transfer] credits were given to [src.account_holder]'s account from income.")
@@ -248,4 +271,20 @@
/datum/bank_account/remote // Bank account not belonging to the local station
add_to_accounts = FALSE
/**
* Add log to transactions history. Deletes the oldest log when the history has more than 20 entries.
* Main format: Category: Reason in Reason. Example: Vending: Machinery Using
* Arguments:
* * adjusted_money - How much was added, negative values removing cash.
* * reason - The reason of interact with balance, for example, "Bought chips" or "Payday".
*/
/datum/bank_account/proc/add_log_to_history(adjusted_money, reason)
if(transaction_history.len >= 20)
transaction_history.Cut(1,2)
transaction_history += list(list(
"adjusted_money" = adjusted_money,
"reason" = reason,
))
#undef DUMPTIME
+2 -2
View File
@@ -262,7 +262,7 @@
/// Exit checks in case the user cancelled or entered an invalid amount
if(!amount || QDELETED(user) || QDELETED(src) || !user.canUseTopic(src, be_close = TRUE, no_dexterity = FALSE, no_tk = TRUE))
return FALSE
if(!payee.adjust_money(-amount))
if(!payee.adjust_money(-amount, "Holopay: [capitalize(name)]"))
balloon_alert(user, "insufficient credits")
to_chat(user, span_warning("You don't have the money to pay for this."))
return FALSE
@@ -281,7 +281,7 @@
*/
/obj/structure/holopay/proc/alert_buyer(payee, amount)
/// Pay the owner
linked_card.registered_account.adjust_money(amount)
linked_card.registered_account.adjust_money(amount, "Holopay: [name]")
/// Make alerts
linked_card.registered_account.bank_card_talk("[payee] has deposited [amount] cr at your holographic pay stand.")
say("Thank you for your patronage, [payee]!")
@@ -104,7 +104,7 @@
if(!current_user.has_money(active_request.value) || (current_user.account_holder != active_request.owner))
playsound(computer, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
return
request_target.transfer_money(current_user, active_request.value)
request_target.transfer_money(current_user, active_request.value, "Bounties: Request Completed")
computer.say("Paid out [active_request.value] credits.")
GLOB.request_list.Remove(active_request)
return TRUE
@@ -0,0 +1,82 @@
/datum/computer_file/program/nt_pay
filename = "ntpay"
filedesc = "Nanotrasen Pay System"
category = PROGRAM_CATEGORY_MISC
program_icon_state = "generic"
extended_desc = "An application that locally (in your sector) helps to transfer money or track your expenses and profits."
size = 2
tgui_id = "NtosPay"
program_icon = "money-bill-wave"
usage_flags = PROGRAM_ALL
///Reference to the currently logged in user.
var/datum/bank_account/current_user
///Pay token, by which we can send credits
var/token
///Amount of credits, which we sends
var/money_to_send = 0
///Pay token what we want to find
var/wanted_token
/datum/computer_file/program/nt_pay/ui_act(action, list/params, datum/tgui/ui)
. = ..()
if(.)
return
switch(action)
if("Transaction")
token = params["token"]
money_to_send = params["amount"]
var/datum/bank_account/recipient
if(!token)
return to_chat(usr, span_notice("You need to enter your transfer target's pay token."))
if(!money_to_send)
return to_chat(usr, span_notice("You need to specify how much you're sending."))
if(token == current_user.pay_token)
return to_chat(usr, span_notice("You can't send credits to yourself."))
for(var/account as anything in SSeconomy.bank_accounts_by_id)
var/datum/bank_account/acc = SSeconomy.bank_accounts_by_id[account]
if(acc.pay_token == token)
recipient = acc
break
if(!recipient)
return to_chat(usr, span_notice("The app can't find who you're trying to pay. Did you enter the pay token right?"))
if(!current_user.has_money(money_to_send))
return current_user.bank_card_talk("You cannot afford it.")
recipient.bank_card_talk("You received [money_to_send] credit(s). Reason: transfer from [current_user.account_holder]")
recipient.transfer_money(current_user, money_to_send)
current_user.bank_card_talk("You send [money_to_send] credit(s) to [recipient.account_holder]. Now you have [current_user.account_balance] credit(s)")
if("GetPayToken")
wanted_token = null
for(var/account in SSeconomy.bank_accounts_by_id)
var/datum/bank_account/acc = SSeconomy.bank_accounts_by_id[account]
if(acc.account_holder == params["wanted_name"])
wanted_token = "Token: [acc.pay_token]"
break
if(!wanted_token)
return wanted_token = "Account \"[params["wanted_name"]]\" not found."
/datum/computer_file/program/nt_pay/ui_data(mob/user)
var/list/data = get_header_data()
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
if(card_slot && card_slot.stored_card && card_slot.stored_card.registered_account)
current_user = card_slot.stored_card.registered_account
else
current_user = null
if(!current_user)
data["name"] = null
else
data["name"] = current_user.account_holder
data["owner_token"] = current_user.pay_token
data["money"] = current_user.account_balance
data["wanted_token"] = wanted_token
data["transaction_list"] = current_user.transaction_history
return data
@@ -185,6 +185,7 @@
. = ..()
store_file(new /datum/computer_file/program/messenger)
store_file(new /datum/computer_file/program/nt_pay)
store_file(new /datum/computer_file/program/notepad)
// For borg integrated tablets. No downloader.
@@ -193,7 +193,7 @@
var/obj/item/card/id/ID = I
var/datum/bank_account/account = ID.registered_account
var/target_credits = total_price - credits
if(!account.adjust_money(-target_credits))
if(!account.adjust_money(-target_credits, "Vending: Laptop Vendor"))
say("Insufficient credits on card to purchase!")
return
credits += target_credits
+4 -4
View File
@@ -276,8 +276,8 @@
var/datum/bank_account/credit_card_details = user.get_bank_account()
if(user in gun_owners)
if(multi_payment && credit_card_details)
if(credit_card_details.adjust_money(-payment_amount))
pin_owner.registered_account.adjust_money(payment_amount)
if(credit_card_details.adjust_money(-payment_amount, "Firing Pin: Gun Rent"))
pin_owner.registered_account.adjust_money(payment_amount, "Firing Pin: Payout For Gun Rent")
return TRUE
to_chat(user, span_warning("ERROR: User balance insufficent for successful transaction!"))
return FALSE
@@ -290,8 +290,8 @@
return FALSE
switch(license_request)
if("Yes")
if(credit_card_details.adjust_money(-payment_amount))
pin_owner.registered_account.adjust_money(payment_amount)
if(credit_card_details.adjust_money(-payment_amount, "Firing Pin: Gun License"))
pin_owner.registered_account.adjust_money(payment_amount, "Firing Pin: Gun License Bought")
gun_owners += user
to_chat(user, span_notice("Gun license purchased, have a secure day!"))
active_prompt = FALSE
+1 -1
View File
@@ -256,7 +256,7 @@
to_chat(chap, span_warning("[GLOB.deity] refuses to heal this metallic taint!"))
return TRUE
account.adjust_money(-GREEDY_HEAL_COST)
account.adjust_money(-GREEDY_HEAL_COST, "Church Donation: Treatment")
var/heal_amt = 30
var/list/hurt_limbs = blessed.get_damaged_bodyparts(1, 1, null, BODYTYPE_ORGANIC)
if(hurt_limbs.len)
+1 -1
View File
@@ -278,7 +278,7 @@
if(!account || account.account_balance < money_cost)
to_chat(user, span_warning("This rite requires more money!"))
return FALSE
account.adjust_money(-money_cost)
account.adjust_money(-money_cost, "Church Donation: Rite")
. = ..()
/datum/religion_rites/greed/vendatray
@@ -294,7 +294,7 @@
var/datum/bank_account/winner_account = winner.get_bank_account()
if(!loser_account || !winner_account)//the winner is pretty owned in this case but whatever shoulda read the fine print of the contract
return
winner_account.transfer_money(loser_account, loser_account.account_balance)
winner_account.transfer_money(loser_account, loser_account.account_balance, "Bet: Sparring")
if(STAKES_YOUR_SOUL)
var/turf/shard_turf = get_turf(loser)
if(!shard_turf)
+1 -1
View File
@@ -227,7 +227,7 @@
if(!account.has_money(deposit_value))
say("You do not possess enough credits.")
return
account.adjust_money(-deposit_value) //The money vanishes, not paid to any accounts.
account.adjust_money(-deposit_value, "Vending: B.E.P.I.S. Chamber") //The money vanishes, not paid to any accounts.
SSblackbox.record_feedback("amount", "BEPIS_credits_spent", deposit_value)
log_econ("[deposit_value] credits were inserted into [src] by [account.account_holder]")
banked_cash += deposit_value
+2 -2
View File
@@ -328,11 +328,11 @@
if(account)
if(account.account_balance < threshold - payees[AM])
account.adjust_money(-account.account_balance)
account.adjust_money(-account.account_balance, "Scanner Gate: Entry Fee")
payees[AM] += account.account_balance
else
var/money_owed = threshold - payees[AM]
account.adjust_money(-money_owed)
account.adjust_money(-money_owed, "Scanner Gate: Partial Entry Fee")
payees[AM] += money_owed
//Here is all the possible paygate payment methods.
+1 -1
View File
@@ -147,7 +147,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
else
paying_for_this = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(paying_for_this)
if(!paying_for_this.adjust_money(-price))
if(!paying_for_this.adjust_money(-price, "Cargo: [spawning_order.pack.name]"))
if(spawning_order.paying_account)
paying_for_this.bank_card_talk("Cargo order #[spawning_order.id] rejected due to lack of funds. Credits required: [price]")
continue
+3 -3
View File
@@ -1081,7 +1081,7 @@ GLOBAL_LIST_EMPTY(vending_products)
price_to_use = R.custom_premium_price ? R.custom_premium_price : extra_price
if(LAZYLEN(R.returned_products))
price_to_use = 0 //returned items are free
if(price_to_use && !account.adjust_money(-price_to_use))
if(price_to_use && !account.adjust_money(-price_to_use, "Vending: [R.name]"))
say("You do not possess the funds to purchase [R.name].")
flick(icon_deny,src)
vend_ready = TRUE
@@ -1393,8 +1393,8 @@ GLOBAL_LIST_EMPTY(vending_products)
balloon_alert(user, "insufficient funds")
return TRUE
/// Make the transaction
payee.adjust_money(-dispensed_item.custom_price)
linked_account.adjust_money(dispensed_item.custom_price)
payee.adjust_money(-dispensed_item.custom_price, , "Vending: [dispensed_item]")
linked_account.adjust_money(dispensed_item.custom_price, "Vending: [dispensed_item] Bought")
linked_account.bank_card_talk("[payee.account_holder] made a [dispensed_item.custom_price] \
cr purchase at your custom vendor.")
/// Log the transaction
+1
View File
@@ -3860,6 +3860,7 @@
#include "code\modules\modular_computers\file_system\programs\jobmanagement.dm"
#include "code\modules\modular_computers\file_system\programs\newscasterapp.dm"
#include "code\modules\modular_computers\file_system\programs\notepad.dm"
#include "code\modules\modular_computers\file_system\programs\nt_pay.dm"
#include "code\modules\modular_computers\file_system\programs\ntdownloader.dm"
#include "code\modules\modular_computers\file_system\programs\ntmessenger.dm"
#include "code\modules\modular_computers\file_system\programs\ntnrc_client.dm"
+180
View File
@@ -0,0 +1,180 @@
import { NtosWindow } from '../layouts';
import { useBackend } from '../backend';
import { Stack, Section, Box, Button, Input, Table, Tooltip, NoticeBox, Divider, RestrictedInput } from '../components';
type Data = {
name: string;
owner_token: string;
money: number;
transaction_list: Transactions[];
wanted_token: string;
};
type Transactions = {
adjusted_money: number;
reason: string;
};
let name_to_token, money_to_send, token;
export const NtosPay = (props, context) => {
const { data } = useBackend<Data>(context);
const { name } = data;
if (!name) {
return (
<NtosWindow width={512} height={130}>
<NtosWindow.Content>
<NoticeBox>
You need to insert your ID card into the card slot in order to use
this application.
</NoticeBox>
</NtosWindow.Content>
</NtosWindow>
);
}
return (
<NtosWindow width={495} height={655}>
<NtosWindow.Content>
<Stack fill vertical>
<Stack.Item>
<Introduction />
</Stack.Item>
<Stack.Item>
<TransferSection />
</Stack.Item>
<Stack.Item grow>
<TransactionHistory />
</Stack.Item>
</Stack>
</NtosWindow.Content>
</NtosWindow>
);
};
/** Displays the user's name and balance. */
const Introduction = (props, context) => {
const { data } = useBackend<Data>(context);
const { name, owner_token, money } = data;
return (
<Section textAlign="center">
<Table>
<Table.Row>Hi, {name}.</Table.Row>
<Table.Row>Your pay token is {owner_token}.</Table.Row>
<Table.Row>
Account balance: {money} credit{money === 1 ? '' : 's'}
</Table.Row>
</Table>
</Section>
);
};
/** Displays the transfer section. */
const TransferSection = (props, context) => {
const { act, data } = useBackend<Data>(context);
const { money, wanted_token } = data;
return (
<Stack>
<Stack.Item>
<Section vertical title="Transfer Money">
<Box>
<Tooltip
content="Enter the pay token of the account you want to trasfer credits."
position="top">
<Input
placeholder="Pay Token"
width="190px"
onChange={(e, value) => (token = value)}
/>
</Tooltip>
</Box>
<Tooltip
content="Enter amount of credits to transfer."
position="top">
<RestrictedInput
width="83px"
minValue={1}
maxValue={money}
onChange={(_, value) => (money_to_send = value)}
value={1}
/>
</Tooltip>
<Button
content="Send credits"
onClick={() =>
act('Transaction', {
token: token,
amount: money_to_send,
})
}
/>
</Section>
</Stack.Item>
<Stack.Item>
<Section title="Get Token" width="270px" height="98px">
<Box>
<Input
placeholder="Full name of account."
width="190px"
onChange={(e, value) => (name_to_token = value)}
/>
<Button
content="Get it"
onClick={() =>
act('GetPayToken', {
wanted_name: name_to_token,
})
}
/>
</Box>
<Divider hidden />
<Box nowrap>{wanted_token}</Box>
</Section>
</Stack.Item>
</Stack>
);
};
/** Displays the transaction history. */
const TransactionHistory = (props, context) => {
const { data } = useBackend<Data>(context);
const { transaction_list = [] } = data;
return (
<Section fill title="Transaction History">
<Section fill scrollable title={<TableHeaders />}>
<Table>
{transaction_list.map((log) => (
<Table.Row
key={log}
className="candystripe"
color={log.adjusted_money < 1 ? 'red' : 'green'}>
<Table.Cell width="100px">
{log.adjusted_money > 1 ? '+' : ''}
{log.adjusted_money}
</Table.Cell>
<Table.Cell textAlign="center">{log.reason}</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
</Section>
);
};
/** Renders a set of sticky headers */
const TableHeaders = (props, context) => {
return (
<Table>
<Table.Row>
<Table.Cell color="label" width="100px">
Amount
</Table.Cell>
<Table.Cell color="label" textAlign="center">
Reason
</Table.Cell>
</Table.Row>
</Table>
);
};