This commit is contained in:
hackerESQ
2025-09-28 21:13:52 -05:00
parent 8908e2da02
commit c6032c5b66
7 changed files with 88 additions and 86 deletions
+41 -38
View File
@@ -1,25 +1,28 @@
<?php <?php
declare(strict_types=1);
namespace App\Livewire\Datatables; namespace App\Livewire\Datatables;
use App\Models\Holding; use App\Models\Holding;
use Illuminate\Support\Number;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Rappasoft\LaravelLivewireTables\Views\Column; use Illuminate\Support\Number;
use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\DataTableComponent;
use Rappasoft\LaravelLivewireTables\Views\Column;
class HoldingsTable extends DataTableComponent class HoldingsTable extends DataTableComponent
{ {
public $portfolio; public $portfolio;
public array $hiddenColumns = []; public array $hiddenColumns = [];
public function mount ($portfolio): void public function mount($portfolio): void
{ {
// //
} }
public function builder(): Builder public function builder(): Builder
{ {
return Holding::query() return Holding::query()
->portfolio($this->portfolio->id) ->portfolio($this->portfolio->id)
->with(['market_data']) ->with(['market_data'])
@@ -34,65 +37,65 @@ class HoldingsTable extends DataTableComponent
$this->hiddenColumns = ['name', 'average_cost_basis', 'market_value', 'fifty_two_week_low', 'fifty_two_week_high']; $this->hiddenColumns = ['name', 'average_cost_basis', 'market_value', 'fifty_two_week_low', 'fifty_two_week_high'];
$this->setTableWrapperAttributes([ $this->setTableWrapperAttributes([
'default' => false, 'default' => false,
'default-styling' => false, 'default-styling' => false,
'default-colors' => false, 'default-colors' => false,
'class' => 'overflow-scroll' 'class' => 'overflow-scroll',
]); ]);
$this->setTableAttributes([ $this->setTableAttributes([
'default' => false, 'default' => false,
'default-styling' => false, 'default-styling' => false,
'default-colors' => false, 'default-colors' => false,
'class' => 'table', 'class' => 'table',
]); ]);
$this->setTheadAttributes([ $this->setTheadAttributes([
'default' => false, 'default' => false,
'default-styling' => true, 'default-styling' => true,
'default-colors' => false, 'default-colors' => false,
]); ]);
$this->setThAttributes(function(Column $column) { $this->setThAttributes(function (Column $column) {
$attributes = [ $attributes = [
'default' => false, 'default' => false,
'default-styling' => false, 'default-styling' => false,
'default-colors' => false, 'default-colors' => false,
'class' => 'text-xs font-medium whitespace-nowrap uppercase tracking-wider text-nowrap' 'class' => 'text-xs font-medium whitespace-nowrap uppercase tracking-wider text-nowrap',
]; ];
if (in_array($column->getField(), $this->hiddenColumns)) { if (in_array($column->getField(), $this->hiddenColumns)) {
$attributes['class'] = $attributes['class'] . ' hidden md:table-cell'; $attributes['class'] = $attributes['class'].' hidden md:table-cell';
} }
return $attributes; return $attributes;
}); });
$this->setThSortButtonAttributes(fn() => [ $this->setThSortButtonAttributes(fn () => [
'default' => false, 'default' => false,
'default-styling' => true, 'default-styling' => true,
'default-colors' => false, 'default-colors' => false,
'class' => 'cursor-pointer' 'class' => 'cursor-pointer',
]); ]);
$this->setTbodyAttributes([ $this->setTbodyAttributes([
'default' => false,
'default-styling' => true,
'default-colors' => false,
]);
$this->setTrAttributes(fn() => [
'default' => false, 'default' => false,
'default-styling' => true, 'default-styling' => true,
'default-colors' => false, 'default-colors' => false,
'class' => 'cursor-pointer hover:bg-neutral/25'
]); ]);
$this->setTdAttributes(function(Column $column) { $this->setTrAttributes(fn () => [
'default' => false,
'default-styling' => true,
'default-colors' => false,
'class' => 'cursor-pointer hover:bg-neutral/25',
]);
$this->setTdAttributes(function (Column $column) {
$attributes = [ $attributes = [
'default' => false, 'default' => false,
'default-styling' => false, 'default-styling' => false,
'default-colors' => false, 'default-colors' => false,
'class' => 'text-nowrap' 'class' => 'text-nowrap',
]; ];
if (in_array($column->getField(), $this->hiddenColumns)) { if (in_array($column->getField(), $this->hiddenColumns)) {
$attributes['class'] = $attributes['class'] . ' hidden md:table-cell'; $attributes['class'] = $attributes['class'].' hidden md:table-cell';
} }
return $attributes; return $attributes;
@@ -107,11 +110,11 @@ class HoldingsTable extends DataTableComponent
$this->setPrimaryKey('id'); $this->setPrimaryKey('id');
$this->setTableRowUrl(function($row) { $this->setTableRowUrl(function ($row) {
return route('holding.show', ['portfolio' => $row->portfolio_id, 'symbol' => $row->symbol]); return route('holding.show', ['portfolio' => $row->portfolio_id, 'symbol' => $row->symbol]);
})->setTableRowUrlTarget(function($row) { })->setTableRowUrlTarget(function ($row) {
return 'navigate'; return 'navigate';
}); });
} }
@@ -127,19 +130,19 @@ class HoldingsTable extends DataTableComponent
->sortable(), ->sortable(),
Column::make(__('Average Cost Basis'), 'average_cost_basis') Column::make(__('Average Cost Basis'), 'average_cost_basis')
->sortable() ->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency) ), ->format(fn ($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency)),
Column::make(__('Total Cost Basis'), 'total_cost_basis') Column::make(__('Total Cost Basis'), 'total_cost_basis')
->sortable() ->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency) ), ->format(fn ($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency)),
Column::make(__('Market Value'), 'market_data.market_value') Column::make(__('Market Value'), 'market_data.market_value')
->sortable() ->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency) ), ->format(fn ($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency)),
Column::make(__('Total Market Value')) Column::make(__('Total Market Value'))
->sortable(fn (Builder $query, string $direction) => $query->orderBy('total_market_value', $direction)) ->sortable(fn (Builder $query, string $direction) => $query->orderBy('total_market_value', $direction))
->label(fn ($row) => Number::currency($row->total_market_value ?? 0, $row->market_data?->currency)), ->label(fn ($row) => Number::currency($row->total_market_value ?? 0, $row->market_data?->currency)),
Column::make(__('Market Gain/Loss')) Column::make(__('Market Gain/Loss'))
->html() ->html()
->label(fn($row) => Number::currency($row->market_gain_dollars ?? 0, $row->market_data?->currency) . view('components.ui.gain-loss-arrow-badge', [ ->label(fn ($row) => Number::currency($row->market_gain_dollars ?? 0, $row->market_data?->currency).view('components.ui.gain-loss-arrow-badge', [
'costBasis' => $row->average_cost_basis, 'costBasis' => $row->average_cost_basis,
'marketValue' => $row->market_data?->market_value, 'marketValue' => $row->market_data?->market_value,
'small' => true, 'small' => true,
@@ -147,22 +150,22 @@ class HoldingsTable extends DataTableComponent
->sortable(fn (Builder $query, string $direction) => $query->orderBy('market_gain_dollars', $direction)), ->sortable(fn (Builder $query, string $direction) => $query->orderBy('market_gain_dollars', $direction)),
Column::make(__('Realized Gain/Loss'), 'realized_gain_dollars') Column::make(__('Realized Gain/Loss'), 'realized_gain_dollars')
->sortable() ->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency) ), ->format(fn ($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency)),
Column::make(__('Dividends Earned'), 'dividends_earned') Column::make(__('Dividends Earned'), 'dividends_earned')
->sortable() ->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency) ), ->format(fn ($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency)),
Column::make(__('52 week low'), 'market_data.fifty_two_week_low') Column::make(__('52 week low'), 'market_data.fifty_two_week_low')
->sortable() ->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency) ), ->format(fn ($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency)),
Column::make(__('52 week high'), 'market_data.fifty_two_week_high') Column::make(__('52 week high'), 'market_data.fifty_two_week_high')
->sortable() ->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency) ), ->format(fn ($value, $row) => Number::currency($value ?? 0, $row->market_data?->currency)),
Column::make(__('Number of Transactions')) Column::make(__('Number of Transactions'))
->sortable(fn (Builder $query, string $direction) => $query->orderBy('num_transactions', $direction)) ->sortable(fn (Builder $query, string $direction) => $query->orderBy('num_transactions', $direction))
->label(fn ($row) => $row->num_transactions), ->label(fn ($row) => $row->num_transactions),
Column::make(__('Last Refreshed'), 'market_data.updated_at') Column::make(__('Last Refreshed'), 'market_data.updated_at')
->sortable() ->sortable()
->format(fn($value) => \Carbon\Carbon::parse($value)->diffForHumans() ) ->format(fn ($value) => \Carbon\Carbon::parse($value)->diffForHumans()),
]; ];
} }
} }
+37 -35
View File
@@ -1,24 +1,26 @@
<?php <?php
declare(strict_types=1);
namespace App\Livewire\Datatables; namespace App\Livewire\Datatables;
use App\Models\Transaction; use App\Models\Transaction;
use Illuminate\Support\Number;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Rappasoft\LaravelLivewireTables\Views\Column; use Illuminate\Support\Number;
use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\DataTableComponent;
use Rappasoft\LaravelLivewireTables\Views\Column;
class TransactionsTable extends DataTableComponent class TransactionsTable extends DataTableComponent
{ {
public array $hiddenColumns = []; public array $hiddenColumns = [];
public function mount (): void public function mount(): void
{ {
// //
} }
public function builder(): Builder public function builder(): Builder
{ {
return Transaction::query() return Transaction::query()
->with(['portfolio', 'market_data']) ->with(['portfolio', 'market_data'])
->myTransactions() ->myTransactions()
@@ -36,65 +38,65 @@ class TransactionsTable extends DataTableComponent
$this->hiddenColumns = ['name', 'cost_basis', 'gain_dollars']; $this->hiddenColumns = ['name', 'cost_basis', 'gain_dollars'];
$this->setTableWrapperAttributes([ $this->setTableWrapperAttributes([
'default' => false, 'default' => false,
'default-styling' => false, 'default-styling' => false,
'default-colors' => false, 'default-colors' => false,
'class' => 'overflow-scroll' 'class' => 'overflow-scroll',
]); ]);
$this->setTableAttributes([ $this->setTableAttributes([
'default' => false, 'default' => false,
'default-styling' => false, 'default-styling' => false,
'default-colors' => false, 'default-colors' => false,
'class' => 'table', 'class' => 'table',
]); ]);
$this->setTheadAttributes([ $this->setTheadAttributes([
'default' => false, 'default' => false,
'default-styling' => true, 'default-styling' => true,
'default-colors' => false, 'default-colors' => false,
]); ]);
$this->setThAttributes(function(Column $column) { $this->setThAttributes(function (Column $column) {
$attributes = [ $attributes = [
'default' => false, 'default' => false,
'default-styling' => false, 'default-styling' => false,
'default-colors' => false, 'default-colors' => false,
'class' => 'text-xs font-medium whitespace-nowrap uppercase tracking-wider text-nowrap' 'class' => 'text-xs font-medium whitespace-nowrap uppercase tracking-wider text-nowrap',
]; ];
if (in_array($column->getField(), $this->hiddenColumns)) { if (in_array($column->getField(), $this->hiddenColumns)) {
$attributes['class'] = $attributes['class'] . ' hidden md:table-cell'; $attributes['class'] = $attributes['class'].' hidden md:table-cell';
} }
return $attributes; return $attributes;
}); });
$this->setThSortButtonAttributes(fn() => [ $this->setThSortButtonAttributes(fn () => [
'default' => false, 'default' => false,
'default-styling' => true, 'default-styling' => true,
'default-colors' => false, 'default-colors' => false,
'class' => 'cursor-pointer' 'class' => 'cursor-pointer',
]); ]);
$this->setTbodyAttributes([ $this->setTbodyAttributes([
'default' => false,
'default-styling' => true,
'default-colors' => false,
]);
$this->setTrAttributes(fn() => [
'default' => false, 'default' => false,
'default-styling' => true, 'default-styling' => true,
'default-colors' => false, 'default-colors' => false,
'class' => 'cursor-pointer hover:bg-neutral/25'
]); ]);
$this->setTdAttributes(function(Column $column) { $this->setTrAttributes(fn () => [
'default' => false,
'default-styling' => true,
'default-colors' => false,
'class' => 'cursor-pointer hover:bg-neutral/25',
]);
$this->setTdAttributes(function (Column $column) {
$attributes = [ $attributes = [
'default' => false, 'default' => false,
'default-styling' => false, 'default-styling' => false,
'default-colors' => false, 'default-colors' => false,
'class' => 'text-nowrap' 'class' => 'text-nowrap',
]; ];
if (in_array($column->getField(), $this->hiddenColumns)) { if (in_array($column->getField(), $this->hiddenColumns)) {
$attributes['class'] = $attributes['class'] . ' hidden md:table-cell'; $attributes['class'] = $attributes['class'].' hidden md:table-cell';
} }
return $attributes; return $attributes;
@@ -111,11 +113,11 @@ class TransactionsTable extends DataTableComponent
$this->setPrimaryKey('id'); $this->setPrimaryKey('id');
$this->setTableRowUrl(function($row) { $this->setTableRowUrl(function ($row) {
return route('holding.show', ['portfolio' => $row->portfolio_id, 'symbol' => $row->symbol]); return route('holding.show', ['portfolio' => $row->portfolio_id, 'symbol' => $row->symbol]);
})->setTableRowUrlTarget(function($row) { })->setTableRowUrlTarget(function ($row) {
return 'navigate'; return 'navigate';
}); });
} }
@@ -123,10 +125,10 @@ class TransactionsTable extends DataTableComponent
public function columns(): array public function columns(): array
{ {
return [ return [
Column::make(__('Date'), 'date') Column::make(__('Date'), 'date')
->sortable() ->sortable()
->format(fn($value) => \Carbon\Carbon::parse($value)->format('M d, Y') ), ->format(fn ($value) => \Carbon\Carbon::parse($value)->format('M d, Y')),
Column::make(__('Portfolio'), 'portfolio.title') Column::make(__('Portfolio'), 'portfolio.title')
->sortable(), ->sortable(),
Column::make(__('Symbol'), 'symbol') Column::make(__('Symbol'), 'symbol')
@@ -134,14 +136,14 @@ class TransactionsTable extends DataTableComponent
Column::make(__('Name'), 'market_data.name') Column::make(__('Name'), 'market_data.name')
->sortable(), ->sortable(),
Column::make(__('Type'), 'transaction_type') Column::make(__('Type'), 'transaction_type')
->label(fn($row) => view('components.ui.badge', [ ->label(fn ($row) => view('components.ui.badge', [
'value' => $row->split ? 'SPLIT' 'value' => $row->split ? 'SPLIT'
: ($row->reinvested_dividend : ($row->reinvested_dividend
? 'REINVEST' ? 'REINVEST'
: $row->transaction_type), : $row->transaction_type),
'class' => ($row->transaction_type == 'BUY' 'class' => ($row->transaction_type == 'BUY'
? 'badge-success' ? 'badge-success'
: 'badge-error') . ' badge-sm mr-3', : 'badge-error').' badge-sm mr-3',
])) ]))
->sortable(fn (Builder $query, string $direction) => $query->orderBy('transaction_type', $direction)), ->sortable(fn (Builder $query, string $direction) => $query->orderBy('transaction_type', $direction)),
Column::make(__('Quantity'), 'quantity') Column::make(__('Quantity'), 'quantity')
-3
View File
@@ -30,9 +30,6 @@ trait Toast
$this->js('toast('.json_encode(['toast' => $toast]).')'); $this->js('toast('.json_encode(['toast' => $toast]).')');
// session()->flash('ib.toast.title', $title);
// session()->flash('ib.toast.description', $description);
if ($redirectTo) { if ($redirectTo) {
return $this->redirect($redirectTo, navigate: true); return $this->redirect($redirectTo, navigate: true);
} }
+1 -1
View File
@@ -38,7 +38,7 @@
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.23",
"laravel/pint": "^1.13", "laravel/pint": "^1.25",
"laravel/sail": "^1.26", "laravel/sail": "^1.26",
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.0", "nunomaduro/collision": "^8.0",
Generated
+6 -6
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "3c3015ad711087ed55daf3aebcf8b06f", "content-hash": "ad05656be3a8913bba187945f9683b48",
"packages": [ "packages": [
{ {
"name": "aws/aws-crt-php", "name": "aws/aws-crt-php",
@@ -9288,16 +9288,16 @@
}, },
{ {
"name": "laravel/pint", "name": "laravel/pint",
"version": "v1.25.0", "version": "v1.25.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/pint.git", "url": "https://github.com/laravel/pint.git",
"reference": "595de38458c6b0ab4cae4bcc769c2e5c5d5b8e96" "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/595de38458c6b0ab4cae4bcc769c2e5c5d5b8e96", "url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9",
"reference": "595de38458c6b0ab4cae4bcc769c2e5c5d5b8e96", "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -9350,7 +9350,7 @@
"issues": "https://github.com/laravel/pint/issues", "issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint" "source": "https://github.com/laravel/pint"
}, },
"time": "2025-09-17T01:36:44+00:00" "time": "2025-09-19T02:57:12+00:00"
}, },
{ {
"name": "laravel/sail", "name": "laravel/sail",
+1 -1
View File
@@ -16,7 +16,7 @@ mkdir -p storage/framework/cache \
storage/logs storage/logs
timestamp=$(date -u "+[%Y-%m-%d %H:%M:%S]") timestamp=$(date -u "+[%Y-%m-%d %H:%M:%S]")
echo "$timestamp Investbrain starting..." >> storage/logs/laravel.log echo "$timestamp Investbrain starting ($VERSION)..." >> storage/logs/laravel.log
echo -e "\n > Storage directory scaffolding is OK... " echo -e "\n > Storage directory scaffolding is OK... "
@@ -6,10 +6,10 @@
@persist('toast') @persist('toast')
<div <div
x-cloak x-cloak
x-data="{ show: false, timer: '', toast: ''}" x-data="{ show: false, timer: '', toast: '' }"
@toast.window=" @toast.window="
clearTimeout(timer); clearTimeout(timer);
toast = $event.detail.toast toast = $event.detail.toast;
setTimeout(() => show = true, 100); setTimeout(() => show = true, 100);
timer = setTimeout(() => show = false, $event.detail.toast.timeout); timer = setTimeout(() => show = false, $event.detail.toast.timeout);
"> ">