Initialize repo and add session changes (2025-09-08)
This commit is contained in:
40
app/Filament/Widgets/EventsActiveToday.php
Normal file
40
app/Filament/Widgets/EventsActiveToday.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use Filament\Tables;
|
||||
use Filament\Widgets\TableWidget as BaseWidget;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class EventsActiveToday extends BaseWidget
|
||||
{
|
||||
protected static ?string $heading = 'Events active today';
|
||||
protected ?string $pollingInterval = '60s';
|
||||
|
||||
public function table(Tables\Table $table): Tables\Table
|
||||
{
|
||||
$today = Carbon::today()->toDateString();
|
||||
$query = DB::table('events as e')
|
||||
->leftJoin('photos as p', function ($join) use ($today) {
|
||||
$join->on('p.event_id', '=', 'e.id')
|
||||
->whereRaw("date(p.created_at) = ?", [$today]);
|
||||
})
|
||||
->where('e.is_active', 1)
|
||||
->whereDate('e.date', '<=', $today)
|
||||
->selectRaw('e.id, e.slug, e.name, e.date, COUNT(p.id) as uploads_today')
|
||||
->groupBy('e.id', 'e.slug', 'e.name', 'e.date')
|
||||
->orderBy('e.date', 'desc')
|
||||
->limit(10);
|
||||
|
||||
return $table
|
||||
->query($query)
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('id')->label('#')->width('60px'),
|
||||
Tables\Columns\TextColumn::make('slug')->label('Slug')->searchable(),
|
||||
Tables\Columns\TextColumn::make('date')->date(),
|
||||
Tables\Columns\TextColumn::make('uploads_today')->label('Uploads today')->numeric(),
|
||||
])
|
||||
->paginated(false);
|
||||
}
|
||||
}
|
||||
31
app/Filament/Widgets/PlatformStatsWidget.php
Normal file
31
app/Filament/Widgets/PlatformStatsWidget.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
|
||||
use Filament\Widgets\StatsOverviewWidget\Stat;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class PlatformStatsWidget extends BaseWidget
|
||||
{
|
||||
protected ?string $pollingInterval = '30s';
|
||||
|
||||
protected function getStats(): array
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$dayAgo = $now->copy()->subDay();
|
||||
|
||||
$tenants = (int) DB::table('tenants')->count();
|
||||
$events = (int) DB::table('events')->count();
|
||||
$photos = (int) DB::table('photos')->count();
|
||||
$photos24h = (int) DB::table('photos')->where('created_at', '>=', $dayAgo)->count();
|
||||
|
||||
return [
|
||||
Stat::make('Tenants', number_format($tenants)),
|
||||
Stat::make('Events', number_format($events)),
|
||||
Stat::make('Photos', number_format($photos))
|
||||
->description("+{$photos24h} in last 24h"),
|
||||
];
|
||||
}
|
||||
}
|
||||
39
app/Filament/Widgets/RecentPhotosTable.php
Normal file
39
app/Filament/Widgets/RecentPhotosTable.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use Filament\Tables;
|
||||
use Filament\Widgets\TableWidget as BaseWidget;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class RecentPhotosTable extends BaseWidget
|
||||
{
|
||||
protected static ?string $heading = 'Recent uploads';
|
||||
protected int|string|array $columnSpan = 'full';
|
||||
|
||||
public function table(Tables\Table $table): Tables\Table
|
||||
{
|
||||
$query = DB::table('photos')->orderByDesc('created_at')->limit(10);
|
||||
|
||||
return $table
|
||||
->query($query)
|
||||
->columns([
|
||||
Tables\Columns\ImageColumn::make('thumbnail_path')->label('Thumb')->circular(),
|
||||
Tables\Columns\TextColumn::make('id')->label('#'),
|
||||
Tables\Columns\TextColumn::make('event_id')->label('Event'),
|
||||
Tables\Columns\TextColumn::make('likes_count')->label('Likes'),
|
||||
Tables\Columns\TextColumn::make('created_at')->since(),
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\Action::make('feature')
|
||||
->label('Feature')
|
||||
->visible(fn($record) => ! (bool)($record->is_featured ?? 0))
|
||||
->action(fn($record) => DB::table('photos')->where('id', $record->id)->update(['is_featured' => 1, 'updated_at' => now()])),
|
||||
Tables\Actions\Action::make('unfeature')
|
||||
->label('Unfeature')
|
||||
->visible(fn($record) => (bool)($record->is_featured ?? 0))
|
||||
->action(fn($record) => DB::table('photos')->where('id', $record->id)->update(['is_featured' => 0, 'updated_at' => now()])),
|
||||
])
|
||||
->paginated(false);
|
||||
}
|
||||
}
|
||||
33
app/Filament/Widgets/TopTenantsByUploads.php
Normal file
33
app/Filament/Widgets/TopTenantsByUploads.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use Filament\Tables;
|
||||
use Filament\Widgets\TableWidget as BaseWidget;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class TopTenantsByUploads extends BaseWidget
|
||||
{
|
||||
protected static ?string $heading = 'Top tenants by uploads';
|
||||
protected ?string $pollingInterval = '60s';
|
||||
|
||||
public function table(Tables\Table $table): Tables\Table
|
||||
{
|
||||
$query = DB::table('photos as p')
|
||||
->join('events as e', 'e.id', '=', 'p.event_id')
|
||||
->join('tenants as t', 't.id', '=', 'e.tenant_id')
|
||||
->selectRaw('t.id as tenant_id, t.name as tenant_name, COUNT(p.id) as uploads')
|
||||
->groupBy('t.id', 't.name')
|
||||
->orderByDesc('uploads')
|
||||
->limit(5);
|
||||
|
||||
return $table
|
||||
->query($query)
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('tenant_id')->label('#')->width('60px'),
|
||||
Tables\Columns\TextColumn::make('tenant_name')->label('Tenant')->searchable(),
|
||||
Tables\Columns\TextColumn::make('uploads')->label('Uploads')->numeric(),
|
||||
])
|
||||
->paginated(false);
|
||||
}
|
||||
}
|
||||
52
app/Filament/Widgets/UploadsPerDayChart.php
Normal file
52
app/Filament/Widgets/UploadsPerDayChart.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use Filament\Widgets\ChartWidget;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class UploadsPerDayChart extends ChartWidget
|
||||
{
|
||||
protected ?string $heading = 'Uploads (14 days)';
|
||||
protected ?string $maxHeight = '220px';
|
||||
protected ?string $pollingInterval = '60s';
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
// Build last 14 days labels
|
||||
$labels = [];
|
||||
$start = Carbon::now()->startOfDay()->subDays(13);
|
||||
for ($i = 0; $i < 14; $i++) {
|
||||
$labels[] = $start->copy()->addDays($i)->format('Y-m-d');
|
||||
}
|
||||
|
||||
// SQLite-friendly group by date
|
||||
$rows = DB::table('photos')
|
||||
->selectRaw("strftime('%Y-%m-%d', created_at) as d, count(*) as c")
|
||||
->where('created_at', '>=', $start)
|
||||
->groupBy('d')
|
||||
->orderBy('d')
|
||||
->get();
|
||||
$map = collect($rows)->keyBy('d');
|
||||
$data = array_map(fn ($d) => (int) ($map[$d]->c ?? 0), $labels);
|
||||
|
||||
return [
|
||||
'labels' => $labels,
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => 'Uploads',
|
||||
'data' => $data,
|
||||
'borderColor' => '#f59e0b',
|
||||
'backgroundColor' => 'rgba(245, 158, 11, 0.2)',
|
||||
'tension' => 0.3,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function getType(): string
|
||||
{
|
||||
return 'line';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user