Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here

mateusjatenee/crypto-tracker

48 stars
3 code files
View mateusjatenee/crypto-tracker on GitHub

composer.json

Open in GitHub
{
//
"require": {
"php": "^7.3|^8.0",
//
"laravel/framework": "^8.54",
"laravel/jetstream": "^2.4"
},
//
}

app/Http/Livewire/AddTransactionButton.php

Open in GitHub
use App\Models\Asset;
use App\Models\Account;
use App\Transactions\CryptoTransaction;
use Livewire\Component;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
class AddTransactionButton extends Component
{
public Account $account;
 
public bool $newTransactionModalOpen = false;
 
public $state = [
'asset_id' => null,
'asset_price' => 0,
'amount_in_tokens' => 0,
'amount_in_dollars' => 0
];
 
public function render()
{
return view('livewire.add-transaction-button');
}
 
public function addTransaction()
{
$data = Validator::make($this->state, [
'asset_id' => ['required', Rule::exists('assets', 'id')],
'asset_price' => ['required', 'numeric', 'gt:0'],
'amount_in_tokens' => ['required', 'numeric', 'gt:0'],
'amount_in_dollars' => ['required', 'numeric', 'gt:0']
])->validate();
 
$this->account->addTransaction(
CryptoTransaction::fromCrypto(
$data['amount_in_tokens'],
$this->getSelectedAssetProperty()
)
);
 
$this->closeNewTransactionModal();
 
$this->emit('transactionCreated');
}
 
public function closeNewTransactionModal(): void
{
$this->newTransactionModalOpen = false;
}
 
public function getAvailableAssetsProperty()
{
return Asset::all();
}
 
public function getSelectedAssetProperty(): ?Asset
{
return Asset::find($this->state['asset_id']);
}
 
public function changedAsset()
{
$this->calculateAssetPrice();
}
 
public function changedCurrentAssetPrice()
{
$this->state['amount_in_dollars'] = 0;
$this->state['amount_in_tokens'] = 0;
}
 
public function changedAmountOfTokens()
{
$this->state['amount_in_dollars'] = $this->getSelectedAssetProperty()->current_price * $this->state['amount_in_tokens'];
}
 
public function changedAmountOfDollars()
{
$this->state['amount_in_tokens'] = $this->state['amount_in_dollars'] / $this->getSelectedAssetProperty()->current_price;
}
 
public function calculateAssetPrice()
{
$this->state['asset_price'] = $this->getSelectedAssetProperty()->current_price;
}
}

resources/views/livewire/add-transaction-button.blade.php

Open in GitHub
<div>
<x-buttons.branded-button wire:click="$set('newTransactionModalOpen', true)">Add Transaction
</x-buttons.branded-button>
<x-jet-dialog-modal wire:model="newTransactionModalOpen">
<x-slot name="title">
{{ __('New Transaction') }}
</x-slot>
 
<x-slot name="content">
<div class="mt-6 sm:mt-5 space-y-6 sm:space-y-5">
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label for="type" class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
Currency
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<select id="currency" name="currency" wire:model="state.asset_id" wire:change="changedAsset"
class="max-w-lg block focus:ring-indigo-500 focus:border-indigo-500 w-full shadow-sm sm:max-w-xs sm:text-sm border-gray-300 rounded-md">
<option default selected>Select a Crypto</option>
@foreach ($this->availableAssets as $asset)
<option value="{{ $asset->id }}">{{ $asset->name }}</option>
@endforeach
</select>
</div>
</div>
 
@if ($this->selectedAsset)
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label for="name" class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
Current Asset Price
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<div class="max-w-lg flex rounded-md shadow-sm">
<input type="text" name="name" id="name" wire:model="state.asset_price"
wire:change="changedCurrentAssetPrice"
class="flex-1 block w-full focus:ring-blue-500 focus:border-blue-500 min-w-0 rounded-none rounded-r-md sm:text-sm border-gray-300">
</div>
</div>
</div>
@endif
 
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label for="name" class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
Amount in Tokens
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<div class="max-w-lg flex rounded-md shadow-sm">
<input type="text" name="name" id="name" wire:model="state.amount_in_tokens"
wire:change="changedAmountOfTokens"
class="flex-1 block w-full focus:ring-blue-500 focus:border-blue-500 min-w-0 rounded-none rounded-r-md sm:text-sm border-gray-300">
</div>
</div>
</div>
 
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<label for="name" class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
Amount in Dollars
</label>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<div class="max-w-lg flex rounded-md shadow-sm">
<input type="text" name="name" id="name" wire:model="state.amount_in_dollars"
wire:change="changedAmountOfDollars"
class="flex-1 block w-full focus:ring-blue-500 focus:border-blue-500 min-w-0 rounded-none rounded-r-md sm:text-sm border-gray-300">
</div>
</div>
</div>
</div>
</x-slot>
 
<x-slot name="footer">
<x-jet-secondary-button wire:click="closeNewTransactionModal" wire:loading.attr="disabled">
{{ __('Cancel') }}
</x-jet-secondary-button>
 
<x-buttons.branded-button class="ml-2" wire:click="addTransaction"
wire:loading.class="opacity-75" wire:loading.attr="disabled">
{{ __('Save') }}
</x-buttons.branded-button>
</x-slot>
</x-jet-dialog-modal>
</div>

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.