wip
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
$seriesData = array_merge([
|
||||
'chart' => [
|
||||
'type' => "area",
|
||||
'stacked' => true,
|
||||
'stacked' => false,
|
||||
'height' => 300,
|
||||
'foreColor' => "#999",
|
||||
'dropShadow' => [
|
||||
@@ -13,8 +13,11 @@
|
||||
'toolbar' => [
|
||||
'show' => false,
|
||||
],
|
||||
'zoom' => [
|
||||
'enabled' => false
|
||||
]
|
||||
],
|
||||
'colors' => ['#00E396', '#0090FF'],
|
||||
'colors' => ['#3185FC', '#48435C', '#9792E3', '#00E396', '#B74F6F', ],
|
||||
'stroke' => [
|
||||
'curve' => "smooth",
|
||||
'width' => 3
|
||||
@@ -122,7 +125,7 @@
|
||||
legendContainer.innerHTML = ''; // Clear any existing legend items
|
||||
|
||||
chartContext.w.globals.seriesNames.forEach(function (seriesName, i) {
|
||||
|
||||
|
||||
var seriesColor = chartContext.w.config.colors[i];
|
||||
var legendItem = document.createElement('div');
|
||||
legendItem.classList.add('flex', 'items-center', 'm-2', 'cursor-pointer');
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<x-menu-item title="{{ __('Create Portfolio') }}" icon="o-document-plus" link="{{ route('portfolio.create') }}" />
|
||||
</x-menu-sub>
|
||||
<x-menu-item title="{{ __('Transactions') }}" icon="o-banknotes" link="{{ route('transaction.index') }}" />
|
||||
{{-- <x-menu-item title="{{ __('Transactions') }}" icon="o-banknotes" link="{{ route('transaction.index') }}" /> --}}
|
||||
{{-- <x-menu-item title="{{ __('Reporting') }}" icon="o-chart-bar-square" link="####" /> --}}
|
||||
|
||||
</x-menu>
|
||||
|
||||
@@ -25,9 +25,9 @@ new class extends Component {
|
||||
['key' => 'total_cost_basis', 'label' => __('Total Cost Basis')],
|
||||
['key' => 'market_data_market_value', 'label' => __('Market Value')],
|
||||
['key' => 'total_market_value', 'label' => __('Total Market Value')],
|
||||
['key' => 'market_gain_loss_dollars', 'label' => __('Market Gain/Loss')],
|
||||
['key' => 'market_gain_loss_percent', 'label' => __('Market Gain/Loss')],
|
||||
['key' => 'realized_gain_loss_dollars', 'label' => __('Realized Gain/Loss')],
|
||||
['key' => 'market_gain_dollars', 'label' => __('Market Gain/Loss')],
|
||||
['key' => 'market_gain_percent', 'label' => __('Market Gain/Loss')],
|
||||
['key' => 'realized_gain_dollars', 'label' => __('Realized Gain/Loss')],
|
||||
['key' => 'dividends_earned', 'label' => __('Dividends Earned')],
|
||||
['key' => 'market_data_fifty_two_week_low', 'label' => __('52 week low')],
|
||||
['key' => 'market_data_fifty_two_week_high', 'label' => __('52 week high')],
|
||||
@@ -40,9 +40,6 @@ new class extends Component {
|
||||
{
|
||||
return $this->portfolio
|
||||
->holdings()
|
||||
->with(['transactions' => function ($query) {
|
||||
$query->portfolio($this->portfolio->id);
|
||||
}])
|
||||
->withCount(['transactions as num_transactions' => function ($query) {
|
||||
$query->portfolio($this->portfolio->id);
|
||||
}])
|
||||
@@ -52,8 +49,8 @@ new class extends Component {
|
||||
->withAggregate('market_data', 'fifty_two_week_high')
|
||||
->withAggregate('market_data', 'updated_at')
|
||||
->selectRaw('(market_data.market_value * holdings.quantity) AS total_market_value')
|
||||
->selectRaw('((market_data.market_value - holdings.average_cost_basis) * holdings.quantity) AS market_gain_loss_dollars')
|
||||
->selectRaw('(((market_data.market_value - holdings.average_cost_basis) / holdings.average_cost_basis) * 100) AS market_gain_loss_percent')
|
||||
->selectRaw('((market_data.market_value - holdings.average_cost_basis) * holdings.quantity) AS market_gain_dollars')
|
||||
->selectRaw('(((market_data.market_value - holdings.average_cost_basis) / holdings.average_cost_basis) * 100) AS market_gain_percent')
|
||||
->join('market_data', 'holdings.symbol', 'market_data.symbol')
|
||||
->orderBy(...array_values($this->sortBy))
|
||||
->where('quantity', '>', 0)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Models\DailyChange;
|
||||
use App\Models\Portfolio;
|
||||
use Livewire\Attributes\{Title, Rule};
|
||||
use Livewire\Volt\Component;
|
||||
@@ -11,70 +12,83 @@ new class extends Component {
|
||||
public String $name = 'portfolio';
|
||||
public String $scope = 'YTD';
|
||||
public Array $options = [
|
||||
['id' => '1M', 'name' => '1 month'],
|
||||
['id' => '3M', 'name' => '3 months'],
|
||||
['id' => 'YTD', 'name' => 'Year to date'],
|
||||
['id' => '1Y', 'name' => '1 year'],
|
||||
['id' => '3Y', 'name' => '3 years'],
|
||||
['id' => 'ALL', 'name' => 'All time']
|
||||
['id' => '1M', 'name' => '1 month', 'method' => 'subMonths', 'args' => [1]],
|
||||
['id' => '3M', 'name' => '3 months', 'method' => 'subMonths', 'args' => [3]],
|
||||
['id' => 'YTD', 'name' => 'Year to date', 'method' => 'startOfYear', 'args' => []],
|
||||
['id' => '1Y', 'name' => '1 year', 'method' => 'subYears', 'args' => [1]],
|
||||
['id' => '3Y', 'name' => '3 years', 'method' => 'subYears', 'args' => [3]],
|
||||
['id' => 'ALL', 'name' => 'All time', 'method' => null]
|
||||
];
|
||||
|
||||
// data
|
||||
public Array $myChart;
|
||||
public Array $chartSeries;
|
||||
|
||||
// methods
|
||||
public function mount()
|
||||
{
|
||||
$this->myChart = [
|
||||
$this->chartSeries = $this->generatePerformanceData();
|
||||
}
|
||||
|
||||
public function generatePerformanceData()
|
||||
{
|
||||
$filterMethod = collect($this->options)->where('id', $this->scope)->first();
|
||||
|
||||
$dailyChangeQuery = DailyChange::query();
|
||||
|
||||
if (isset($this->portfolio)) {
|
||||
$dailyChangeQuery->portfolio($this->portfolio->id);
|
||||
} else {
|
||||
$dailyChangeQuery->selectRaw('date,
|
||||
SUM(total_market_value) as total_market_value,
|
||||
SUM(total_cost_basis) as total_cost_basis,
|
||||
SUM(total_gain) as total_gain,
|
||||
SUM(total_dividends_earned) as total_dividends_earned,
|
||||
SUM(realized_gains) as realized_gains'
|
||||
)->groupBy('date');
|
||||
}
|
||||
|
||||
if ($filterMethod['method']) {
|
||||
$dailyChangeQuery->whereDate('date', '>=', now()->{$filterMethod['method']}(...$filterMethod['args']));
|
||||
}
|
||||
|
||||
$dailyChange = $dailyChangeQuery->get();
|
||||
|
||||
return [
|
||||
'series' => [
|
||||
[
|
||||
'name' => __('Total Views'),
|
||||
'data' => $this->generateDateSeries('2024-01-01', '2024-08-01')
|
||||
],
|
||||
'name' => __('Market Value'),
|
||||
'data' => $dailyChange->map(fn($data) => [$data->date, $data->total_market_value])->toArray(),
|
||||
],
|
||||
[
|
||||
'name' => __('Second Views'),
|
||||
'data' => $this->generateDateSeries('2024-01-01', '2024-08-01')
|
||||
],
|
||||
],
|
||||
|
||||
'name' => __('Cost Basis'),
|
||||
'data' => $dailyChange->map(fn($data) => [$data->date, $data->total_cost_basis])->toArray(),
|
||||
],
|
||||
[
|
||||
'name' => __('Market Gain'),
|
||||
'data' => $dailyChange->map(fn($data) => [$data->date, $data->total_gain])->toArray()
|
||||
],
|
||||
[
|
||||
'name' => __('Dividends Earned'),
|
||||
'data' => $dailyChange->map(fn($data) => [$data->date, $data->total_dividends_earned])->toArray()
|
||||
],
|
||||
[
|
||||
'name' => __('Realized Gains'),
|
||||
'data' => $dailyChange->map(fn($data) => [$data->date, $data->realized_gains])->toArray()
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
// $this->marketGainLoss = rand(-200, 3999);
|
||||
}
|
||||
|
||||
public function changeScope($scope)
|
||||
{
|
||||
$this->scope = $scope;
|
||||
|
||||
$this->dispatch('data-scope-updated', $scope);
|
||||
$this->chartSeries = $this->generatePerformanceData();
|
||||
}
|
||||
|
||||
public function getScopeName($scope)
|
||||
{
|
||||
return collect($this->options)->where('id', $scope)['name'];
|
||||
}
|
||||
|
||||
private function generateDateSeries($startDate, $endDate)
|
||||
{
|
||||
$dateArray = [];
|
||||
$currentDate = strtotime($startDate);
|
||||
$endDate = strtotime($endDate);
|
||||
|
||||
while ($currentDate <= $endDate) {
|
||||
// Generate a random integer
|
||||
$randomInt = rand(1000, 3000);
|
||||
|
||||
// Format the current date to 'Y-m-d'
|
||||
$formattedDate = date('Y-m-d', $currentDate);
|
||||
|
||||
// Append the date and random integer to the array
|
||||
$dateArray[] = [$formattedDate, $randomInt];
|
||||
|
||||
// Move to the next day
|
||||
$currentDate = strtotime("+1 day", $currentDate);
|
||||
}
|
||||
|
||||
return $dateArray;
|
||||
return collect($this->options)->where('id', $scope)->first()['name'];
|
||||
}
|
||||
|
||||
}; ?>
|
||||
@@ -90,7 +104,7 @@ new class extends Component {
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<x-button title="{{ __('Reset chart') }}" icon="o-arrow-path" class="btn-ghost btn-sm btn-circle mr-2" id="chart-reset-zoom-{{ $name }}" />
|
||||
{{-- <x-button title="{{ __('Reset chart') }}" icon="o-arrow-path" class="btn-ghost btn-sm btn-circle mr-2" id="chart-reset-zoom-{{ $name }}" /> --}}
|
||||
|
||||
<x-dropdown title="{{ __('Choose time period') }}" label="{{ $scope }}" class="btn-ghost btn-sm">
|
||||
|
||||
@@ -110,7 +124,7 @@ new class extends Component {
|
||||
<div
|
||||
class="h-[280px] mb-5"
|
||||
>
|
||||
<x-ib-apex-chart :series-data="$myChart" :name="$name" />
|
||||
<x-ib-apex-chart :series-data="$chartSeries" :name="$name" />
|
||||
</div>
|
||||
|
||||
</x-card>
|
||||
@@ -53,29 +53,30 @@
|
||||
|
||||
<div class="grid sm:grid-cols-5 gap-5">
|
||||
|
||||
|
||||
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
|
||||
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Market Gain/Loss') }}</div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($portfolio->marketGainLoss) }} </div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($metrics->total_gain_dollars) }} </div>
|
||||
</x-card>
|
||||
|
||||
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
|
||||
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Total Cost Basis') }}</div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($portfolio->totalCostBasis) }} </div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($metrics->total_cost_basis) }} </div>
|
||||
</x-card>
|
||||
|
||||
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
|
||||
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Total Market Value') }}</div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($portfolio->totalMarketValue) }} </div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($metrics->total_market_value) }} </div>
|
||||
</x-card>
|
||||
|
||||
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
|
||||
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Realized Gain/Loss') }}</div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($portfolio->realizedGainLoss) }} </div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($metrics->realized_gain_dollars) }} </div>
|
||||
</x-card>
|
||||
|
||||
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
|
||||
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Dividends Earned') }}</div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($portfolio->dividendsEarned) }} </div>
|
||||
<div class="font-black text-xl"> {{ Number::currency($metrics->total_dividends_earned) }} </div>
|
||||
</x-card>
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user