Chore: Upgrade to Laravel 12 + remove Mary and Jetstream dependencies (#141)

* docs: remove requirement for setting APP_KEY manually

* optimize date picker

* clean up modals

* spot light working

* reorganization

* add lazy load

* wip

* remove filament

* styling
This commit is contained in:
hackerESQ
2025-09-26 17:41:28 -05:00
committed by GitHub
parent 910d426ad4
commit e6f38d9481
146 changed files with 5443 additions and 3909 deletions
+169
View File
@@ -0,0 +1,169 @@
<?php
namespace App\Livewire\Datatables;
use App\Models\Holding;
use Illuminate\Support\Number;
use Illuminate\Database\Eloquent\Builder;
use Rappasoft\LaravelLivewireTables\Views\Column;
use Rappasoft\LaravelLivewireTables\DataTableComponent;
class HoldingsTable extends DataTableComponent
{
public $portfolio;
public array $hiddenColumns = [];
public function mount ($portfolio): void
{
//
}
public function builder(): Builder
{
return Holding::query()
->portfolio($this->portfolio->id)
->with(['market_data'])
->withCount(['transactions as num_transactions' => function ($query) {
return $query->whereRaw('transactions.symbol = holdings.symbol');
}])
->withPerformance();
}
public function configure(): void
{
$this->hiddenColumns = ['name', 'average_cost_basis', 'market_value', 'fifty_two_week_low', 'fifty_two_week_high'];
$this->setTableWrapperAttributes([
'default' => false,
'default-styling' => false,
'default-colors' => false,
'class' => 'overflow-scroll'
]);
$this->setTableAttributes([
'default' => false,
'default-styling' => false,
'default-colors' => false,
'class' => 'table',
]);
$this->setTheadAttributes([
'default' => false,
'default-styling' => true,
'default-colors' => false,
]);
$this->setThAttributes(function(Column $column) {
$attributes = [
'default' => false,
'default-styling' => false,
'default-colors' => false,
'class' => 'text-xs font-medium whitespace-nowrap uppercase tracking-wider text-nowrap'
];
if (in_array($column->getField(), $this->hiddenColumns)) {
$attributes['class'] = $attributes['class'] . ' hidden md:table-cell';
}
return $attributes;
});
$this->setThSortButtonAttributes(fn() => [
'default' => false,
'default-styling' => true,
'default-colors' => false,
'class' => 'cursor-pointer'
]);
$this->setTbodyAttributes([
'default' => false,
'default-styling' => true,
'default-colors' => false,
]);
$this->setTrAttributes(fn() => [
'default' => false,
'default-styling' => true,
'default-colors' => false,
'class' => 'cursor-pointer hover:bg-neutral/25'
]);
$this->setTdAttributes(function(Column $column) {
$attributes = [
'default' => false,
'default-styling' => false,
'default-colors' => false,
'class' => 'text-nowrap'
];
if (in_array($column->getField(), $this->hiddenColumns)) {
$attributes['class'] = $attributes['class'] . ' hidden md:table-cell';
}
return $attributes;
});
$this->setDefaultSort('symbol', 'asc');
$this->setToolsDisabled();
$this->setFooterDisabled();
$this->setPaginationDisabled();
$this->setDisplayPaginationDetailsDisabled();
$this->setPrimaryKey('id');
$this->setTableRowUrl(function($row) {
return route('holding.show', ['portfolio' => $row->portfolio_id, 'symbol' => $row->symbol]);
})->setTableRowUrlTarget(function($row) {
return 'navigate';
});
}
public function columns(): array
{
return [
Column::make(__('Symbol'), 'symbol')
->sortable(),
Column::make(__('Name'), 'market_data.name')
->sortable(),
Column::make(__('Quantity'), 'quantity')
->sortable(),
Column::make(__('Average Cost Basis'), 'average_cost_basis')
->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data->currency) ),
Column::make(__('Total Cost Basis'), 'total_cost_basis')
->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data->currency) ),
Column::make(__('Market Value'), 'market_data.market_value')
->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data->currency) ),
Column::make(__('Total Market Value'))
->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)),
Column::make(__('Market Gain/Loss'))
->html()
->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,
'marketValue' => $row->market_data->market_value,
'small' => true,
]))
->sortable(fn (Builder $query, string $direction) => $query->orderBy('market_gain_dollars', $direction)),
Column::make(__('Realized Gain/Loss'), 'realized_gain_dollars')
->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')
->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data->currency) ),
Column::make(__('52 week low'), 'market_data.fifty_two_week_low')
->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data->currency) ),
Column::make(__('52 week high'), 'market_data.fifty_two_week_high')
->sortable()
->format(fn($value, $row) => Number::currency($value ?? 0, $row->market_data->currency) ),
Column::make(__('Number of Transactions'))
->sortable(fn (Builder $query, string $direction) => $query->orderBy('num_transactions', $direction))
->label(fn ($row) => $row->num_transactions),
Column::make(__('Last Refreshed'), 'market_data.updated_at')
->sortable()
->format(fn($value) => \Carbon\Carbon::parse($value)->diffForHumans() )
];
}
}
@@ -0,0 +1,157 @@
<?php
namespace App\Livewire\Datatables;
use App\Models\Transaction;
use Illuminate\Support\Number;
use Illuminate\Database\Eloquent\Builder;
use Rappasoft\LaravelLivewireTables\Views\Column;
use Rappasoft\LaravelLivewireTables\DataTableComponent;
class TransactionsTable extends DataTableComponent
{
public array $hiddenColumns = [];
public function mount (): void
{
//
}
public function builder(): Builder
{
return Transaction::query()
->with(['portfolio', 'market_data'])
->myTransactions()
->addSelect(['portfolio_id', 'transaction_type', 'split'])
->selectRaw('
CASE
WHEN transaction_type = \'SELL\'
THEN COALESCE(transactions.sale_price - transactions.cost_basis, 0)
ELSE COALESCE(market_data.market_value - transactions.cost_basis, 0)
END AS gain_dollars');
}
public function configure(): void
{
$this->hiddenColumns = ['name', 'cost_basis', 'gain_dollars'];
$this->setTableWrapperAttributes([
'default' => false,
'default-styling' => false,
'default-colors' => false,
'class' => 'overflow-scroll'
]);
$this->setTableAttributes([
'default' => false,
'default-styling' => false,
'default-colors' => false,
'class' => 'table',
]);
$this->setTheadAttributes([
'default' => false,
'default-styling' => true,
'default-colors' => false,
]);
$this->setThAttributes(function(Column $column) {
$attributes = [
'default' => false,
'default-styling' => false,
'default-colors' => false,
'class' => 'text-xs font-medium whitespace-nowrap uppercase tracking-wider text-nowrap'
];
if (in_array($column->getField(), $this->hiddenColumns)) {
$attributes['class'] = $attributes['class'] . ' hidden md:table-cell';
}
return $attributes;
});
$this->setThSortButtonAttributes(fn() => [
'default' => false,
'default-styling' => true,
'default-colors' => false,
'class' => 'cursor-pointer'
]);
$this->setTbodyAttributes([
'default' => false,
'default-styling' => true,
'default-colors' => false,
]);
$this->setTrAttributes(fn() => [
'default' => false,
'default-styling' => true,
'default-colors' => false,
'class' => 'cursor-pointer hover:bg-neutral/25'
]);
$this->setTdAttributes(function(Column $column) {
$attributes = [
'default' => false,
'default-styling' => false,
'default-colors' => false,
'class' => 'text-nowrap'
];
if (in_array($column->getField(), $this->hiddenColumns)) {
$attributes['class'] = $attributes['class'] . ' hidden md:table-cell';
}
return $attributes;
});
$this->setDefaultSort('date', 'desc');
$this->setPerPageAccepted([10, 15, 20]);
$this->setPerPage(15);
$this->setSearchDisabled();
$this->setColumnSelectDisabled();
$this->setPerPageVisibilityDisabled();
$this->setFooterDisabled();
$this->setPrimaryKey('id');
$this->setTableRowUrl(function($row) {
return route('holding.show', ['portfolio' => $row->portfolio_id, 'symbol' => $row->symbol]);
})->setTableRowUrlTarget(function($row) {
return 'navigate';
});
}
public function columns(): array
{
return [
Column::make(__('Date'), 'date')
->sortable()
->format(fn($value) => \Carbon\Carbon::parse($value)->format('M d, Y') ),
Column::make(__('Portfolio'), 'portfolio.title')
->sortable(),
Column::make(__('Symbol'), 'symbol')
->sortable(),
Column::make(__('Name'), 'market_data.name')
->sortable(),
Column::make(__('Type'), 'transaction_type')
->label(fn($row) => view('components.ui.badge', [
'value' => $row->split ? 'SPLIT'
: ($row->reinvested_dividend
? 'REINVEST'
: $row->transaction_type),
'class' => ($row->transaction_type == 'BUY'
? 'badge-success'
: 'badge-error') . ' badge-sm mr-3',
]))
->sortable(fn (Builder $query, string $direction) => $query->orderBy('transaction_type', $direction)),
Column::make(__('Quantity'), 'quantity')
->sortable(),
Column::make(__('Cost Basis'), 'cost_basis')
->sortable(fn (Builder $query, string $direction) => $query->orderBy('cost_basis', $direction))
->label(fn ($row) => Number::currency($row->cost_basis ?? 0, $row->market_data->currency)),
Column::make(__('Gain/Loss'), 'gain_dollars')
->sortable(fn (Builder $query, string $direction) => $query->orderBy('gain_dollars', $direction))
->label(fn ($row) => Number::currency($row->gain_dollars ?? 0, $row->market_data->currency)),
];
}
}