wip more dashboard widgets

This commit is contained in:
hackerESQ
2024-08-22 22:45:17 -05:00
parent d0dafab9f6
commit 6160fd19db
8 changed files with 234 additions and 53 deletions
+18 -4
View File
@@ -3,11 +3,14 @@
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Laravel\Sanctum\HasApiTokens;
use Laravel\Jetstream\HasProfilePhoto;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Staudenmeir\EloquentHasManyDeep\HasManyDeep;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
@@ -19,6 +22,7 @@ class User extends Authenticatable
use Notifiable;
use TwoFactorAuthenticatable;
use HasUuids;
use HasRelationships;
/**
* The attributes that are mass assignable.
@@ -70,8 +74,18 @@ class User extends Authenticatable
return $this->belongsToMany(Portfolio::class)->withPivot('owner');
}
// public function daily_changes()
// {
// return $this->hasMany(DailyChange::class);
// }
public function holdings(): HasManyDeep
{
return $this->hasManyDeep(Holding::class, ['portfolio_user', Portfolio::class]);
}
public function transactions(): HasManyDeep
{
return $this->hasManyDeep(Transaction::class, ['portfolio_user', Portfolio::class]);
}
public function daily_change(): HasManyDeep
{
return $this->hasManyDeep(DailyChange::class, ['portfolio_user', Portfolio::class]);
}
}
+2 -1
View File
@@ -14,7 +14,8 @@
"livewire/volt": "^1.6",
"maatwebsite/excel": "^3.1",
"predis/predis": "^2.2",
"robsontenorio/mary": "^1.35"
"robsontenorio/mary": "^1.35",
"staudenmeir/eloquent-has-many-deep": "^1.20"
},
"require-dev": {
"fakerphp/faker": "^1.23",
Generated
+109 -1
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4dcc44afdbd155cb01d0e00deb3bb4fe",
"content-hash": "87ff0113a9121d64fb4518b040767e96",
"packages": [
{
"name": "bacon/bacon-qr-code",
@@ -4790,6 +4790,114 @@
],
"time": "2024-07-26T15:41:31+00:00"
},
{
"name": "staudenmeir/eloquent-has-many-deep",
"version": "v1.20.2",
"source": {
"type": "git",
"url": "https://github.com/staudenmeir/eloquent-has-many-deep.git",
"reference": "edcce8d8559d9559c997c177de06eb4bc173956d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep/zipball/edcce8d8559d9559c997c177de06eb4bc173956d",
"reference": "edcce8d8559d9559c997c177de06eb4bc173956d",
"shasum": ""
},
"require": {
"illuminate/database": "^11.0",
"php": "^8.2",
"staudenmeir/eloquent-has-many-deep-contracts": "^1.2"
},
"require-dev": {
"awobaz/compoships": "^2.3",
"barryvdh/laravel-ide-helper": "^3.0",
"illuminate/pagination": "^11.0",
"korridor/laravel-has-many-merged": "^1.1",
"mockery/mockery": "^1.6",
"orchestra/testbench": "^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^11.0",
"staudenmeir/eloquent-json-relations": "^1.11",
"staudenmeir/laravel-adjacency-list": "^1.21"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Staudenmeir\\EloquentHasManyDeep\\IdeHelperServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Staudenmeir\\EloquentHasManyDeep\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonas Staudenmeir",
"email": "mail@jonas-staudenmeir.de"
}
],
"description": "Laravel Eloquent HasManyThrough relationships with unlimited levels",
"support": {
"issues": "https://github.com/staudenmeir/eloquent-has-many-deep/issues",
"source": "https://github.com/staudenmeir/eloquent-has-many-deep/tree/v1.20.2"
},
"funding": [
{
"url": "https://paypal.me/JonasStaudenmeir",
"type": "custom"
}
],
"time": "2024-07-12T22:08:11+00:00"
},
{
"name": "staudenmeir/eloquent-has-many-deep-contracts",
"version": "v1.2",
"source": {
"type": "git",
"url": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts.git",
"reference": "bcbe1a921caad7201b324e297eddb696d4bd8647"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep-contracts/zipball/bcbe1a921caad7201b324e297eddb696d4bd8647",
"reference": "bcbe1a921caad7201b324e297eddb696d4bd8647",
"shasum": ""
},
"require": {
"illuminate/database": "^11.0",
"php": "^8.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Staudenmeir\\EloquentHasManyDeepContracts\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonas Staudenmeir",
"email": "mail@jonas-staudenmeir.de"
}
],
"description": "Contracts for staudenmeir/eloquent-has-many-deep",
"support": {
"issues": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/issues",
"source": "https://github.com/staudenmeir/eloquent-has-many-deep-contracts/tree/v1.2"
},
"time": "2024-01-18T01:20:44+00:00"
},
{
"name": "symfony/clock",
"version": "v7.1.1",
+23 -21
View File
@@ -58,17 +58,33 @@
@if (!$user->portfolios->isEmpty())
<x-ib-card title="{{ __('Top performers') }}" class="md:col-span-3">
@php
$users = App\Models\User::take(3)->get();
@endphp
@foreach($users as $user)
<x-list-item no-separator :item="$user" avatar="profile_photo_url" link="/docs/installation" />
@foreach($user->holdings->sortBy('market_gain_percent')->where('quantity', '>', 0)->take(5) as $holding)
<x-list-item no-separator :item="$holding" link="{{ route('portfolio.show', ['portfolio' => $holding->portfolio_id]) }}">
@php
$gainPercent = (($holding->market_data?->market_value - $holding->average_cost_basis) / $holding->average_cost_basis) * 100;
@endphp
<x-slot:value class="flex items-center">
{{ $holding->symbol }}
<x-badge class="{{ $gainPercent > 0 ? 'badge-success' : 'badge-error' }} ml-2 badge-sm" >
<x-slot:value>
{{ Number::percentage($gainPercent) }}
</x-slot:value>
</x-badge>
</x-slot:value>
<x-slot:sub-value>
{{ $holding->market_data?->name }}
</x-slot:sub-value>
</x-list-item>
@endforeach
</x-ib-card>
@endif
{{-- @if (!$user->portfolios->isEmpty())
<x-ib-card title="{{ __('Top headlines') }}" class="md:col-span-3">
@@ -83,20 +99,6 @@
</x-ib-card>
@endif --}}
@if (!$user->portfolios->isEmpty())
<x-ib-card title="{{ __('Recent activity') }}" class="md:col-span-4">
@php
$users = App\Models\User::take(3)->get();
@endphp
@foreach($users as $user)
<x-list-item no-separator :item="$user" avatar="profile_photo_url" link="/docs/installation" />
@endforeach
</x-ib-card>
@endif
</div>
</x-app-layout>
@@ -61,5 +61,42 @@ new class extends Component {
<div class="">
<x-table wire:loading.remove :headers="$headers" :rows="$this->holdings()" :sort-by="$sortBy" />
<x-table wire:loading.remove :headers="$headers" :rows="$this->holdings()" :sort-by="$sortBy">
@scope('cell_average_cost_basis', $row)
{{ Number::currency($row->average_cost_basis ?? 0) }}
@endscope
@scope('cell_total_cost_basis', $row)
{{ Number::currency($row->total_cost_basis ?? 0) }}
@endscope
@scope('cell_realized_gain_dollars', $row)
{{ Number::currency($row->realized_gain_dollars ?? 0) }}
@endscope
@scope('cell_market_gain_dollars', $row)
{{ Number::currency($row->market_gain_dollars ?? 0) }}
@endscope
@scope('cell_market_gain_percent', $row)
{{ Number::percentage($row->market_gain_percent ?? 0) }}
@endscope
@scope('cell_market_data_market_value', $row)
{{ Number::currency($row->market_data_market_value ?? 0) }}
@endscope
@scope('cell_market_data_fifty_two_week_low', $row)
{{ Number::currency($row->market_data_fifty_two_week_low ?? 0) }}
@endscope
@scope('cell_market_data_fifty_two_week_high', $row)
{{ Number::currency($row->market_data_fifty_two_week_high ?? 0) }}
@endscope
@scope('cell_total_market_value', $row)
{{ Number::currency($row->total_market_value ?? 0) }}
@endscope
@scope('cell_dividends_earned', $row)
{{ Number::currency($row->dividends_earned ?? 0) }}
@endscope
@scope('cell_dividends_earned', $row)
{{ Number::currency($row->dividends_earned ?? 0) }}
@endscope
@scope('cell_market_data_updated_at', $row)
{{ \Carbon\Carbon::parse($row->market_data_updated_at)->diffForHumans() }}
@endscope
</x-table>
</div>
@@ -43,10 +43,11 @@ new class extends Component {
$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'
SUM(total_gain) as total_gain'
)->groupBy('date');
// SUM(total_dividends_earned) as total_dividends_earned,
// SUM(realized_gains) as realized_gains
}
if ($filterMethod['method']) {
@@ -70,14 +71,14 @@ new class extends Component {
'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()
],
// [
// '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()
// ],
]
];
}
+28 -14
View File
@@ -81,29 +81,15 @@
</div>
<div class="mt-6 grid md:grid-cols-7 gap-5">
<x-ib-card title="{{ __('Holdings') }}" class="md:col-span-4">
@livewire('holdings-table', [
'portfolio' => $portfolio
])
</x-ib-card>
{{-- <x-ib-card title="{{ __('Top performers') }}" class="md:col-span-3">
@php
$users = App\Models\User::take(3)->get();
@endphp
@foreach($users as $user)
<x-list-item no-separator :item="$user" avatar="profile_photo_url" link="/docs/installation" />
@endforeach
</x-ib-card> --}}
{{-- <x-ib-card title="{{ __('Top headlines') }}" class="md:col-span-3">
@@ -125,6 +111,34 @@
</x-ib-card>
<x-ib-card title="{{ __('Top performers') }}" class="md:col-span-3">
@foreach($portfolio->holdings->sortBy('market_gain_percent')->where('quantity', '>', 0)->take(5) as $holding)
<x-list-item no-separator :item="$holding">
@php
$gainPercent = (($holding->market_data?->market_value - $holding->average_cost_basis) / $holding->average_cost_basis) * 100;
@endphp
<x-slot:value class="flex items-center">
{{ $holding->symbol }}
<x-badge class="{{ $gainPercent > 0 ? 'badge-success' : 'badge-error' }} ml-2 badge-sm" >
<x-slot:value>
{{ Number::percentage($gainPercent) }}
</x-slot:value>
</x-badge>
</x-slot:value>
<x-slot:sub-value>
{{ $holding->market_data?->name }}
</x-slot:sub-value>
</x-list-item>
@endforeach
</x-ib-card>
</div>
</div>
</x-app-layout>
+4
View File
@@ -9,6 +9,10 @@ Route::get('/', function () {
return view('welcome');
});
Route::get('/test', function () {
dd(auth()->user()->holdings()->toSql());
});
Route::middleware(['auth:sanctum', config('jetstream.auth_session'), 'verified'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'show'])->name('dashboard');