230 lines
5.9 KiB
PHP
230 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Party;
|
|
|
|
use App\Enums\Parties as PartyEnum;
|
|
use App\Services\RiksdagenService;
|
|
use Asantibanez\LivewireCharts\Models\ColumnChartModel;
|
|
use Asantibanez\LivewireCharts\Models\PieChartModel;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Livewire\Attributes\Computed;
|
|
use Livewire\Attributes\Lazy;
|
|
use Livewire\Component;
|
|
|
|
#[Lazy()]
|
|
class Show extends Component
|
|
{
|
|
public $partyCode;
|
|
|
|
public $party;
|
|
|
|
public $motions = [];
|
|
|
|
public $members = [];
|
|
|
|
public $votes = [];
|
|
|
|
public $selectedYear = '';
|
|
|
|
private RiksdagenService $service;
|
|
|
|
public function mount($partyCode)
|
|
{
|
|
$this->partyCode = strtoupper($partyCode);
|
|
$this->service = app(RiksdagenService::class);
|
|
|
|
// Find party info
|
|
$this->party = collect(PartyEnum::cases())
|
|
->firstWhere('value', $this->partyCode);
|
|
|
|
if (! $this->party) {
|
|
abort(404);
|
|
}
|
|
|
|
$this->loadPartyData();
|
|
}
|
|
|
|
public function loadPartyData()
|
|
{
|
|
// Load party motions
|
|
$this->loadMotions();
|
|
|
|
// Load party members
|
|
$this->loadMembers();
|
|
|
|
// Load voting data for members
|
|
$this->loadVotingData();
|
|
}
|
|
|
|
public function loadMotions()
|
|
{
|
|
$result = Cache::remember('party_motions_'.$this->partyCode, 60 * 30, function () {
|
|
return $this->service->getPartyMotions($this->partyCode);
|
|
});
|
|
|
|
$this->motions = $result->original->dokumentlista->dokument ?? [];
|
|
|
|
// Set default selected year if motions exist
|
|
if (! empty($this->motions)) {
|
|
$years = collect($this->motions)->pluck('rm')->unique()->sort()->reverse();
|
|
$this->selectedYear = $years->first();
|
|
}
|
|
}
|
|
|
|
public function loadMembers()
|
|
{
|
|
$result = Cache::remember('party_members_'.$this->partyCode, 24 * 60 * 60, function () {
|
|
return $this->service->searchPerson(party: $this->partyCode);
|
|
});
|
|
|
|
$this->members = $result->original->personlista->person ?? [];
|
|
}
|
|
|
|
public function loadVotingData()
|
|
{
|
|
// For now, load voting data for a sample of members due to API limitations
|
|
$sampleMembers = collect($this->members)->take(5);
|
|
|
|
foreach ($sampleMembers as $member) {
|
|
$memberVotes = Cache::remember('member_votes_'.$member->intressent_id, 60 * 60, function () use ($member) {
|
|
return $this->service->searchVotes(mp_id: $member->intressent_id);
|
|
});
|
|
|
|
$votes = $memberVotes->original->voteringlista->votering ?? [];
|
|
$this->votes = array_merge($this->votes, is_array($votes) ? $votes : [$votes]);
|
|
}
|
|
}
|
|
|
|
public function selectYear($year)
|
|
{
|
|
$this->selectedYear = $year;
|
|
}
|
|
|
|
#[Computed()]
|
|
public function motionsByYear()
|
|
{
|
|
$grouped = [];
|
|
foreach ($this->motions as $motion) {
|
|
$rm = $motion->rm;
|
|
if (! isset($grouped[$rm])) {
|
|
$grouped[$rm] = [];
|
|
}
|
|
$grouped[$rm][] = $motion;
|
|
}
|
|
|
|
return $grouped;
|
|
}
|
|
|
|
#[Computed()]
|
|
public function motionStatistics()
|
|
{
|
|
$stats = [
|
|
'total' => count($this->motions),
|
|
'by_year' => [],
|
|
'by_type' => [],
|
|
];
|
|
|
|
foreach ($this->motions as $motion) {
|
|
// By year
|
|
$year = $motion->rm;
|
|
$stats['by_year'][$year] = ($stats['by_year'][$year] ?? 0) + 1;
|
|
|
|
// By type
|
|
$type = $motion->subtyp ?? 'Okänd';
|
|
$stats['by_type'][$type] = ($stats['by_type'][$type] ?? 0) + 1;
|
|
}
|
|
|
|
return $stats;
|
|
}
|
|
|
|
#[Computed()]
|
|
public function votingStatistics()
|
|
{
|
|
$stats = [];
|
|
foreach ($this->votes as $vote) {
|
|
$voteType = $vote->rost ?? 'Okänd';
|
|
$stats[$voteType] = ($stats[$voteType] ?? 0) + 1;
|
|
}
|
|
|
|
return $stats;
|
|
}
|
|
|
|
#[Computed()]
|
|
public function motionsColumnChart()
|
|
{
|
|
$motionStats = $this->motionStatistics;
|
|
|
|
$chart = (new ColumnChartModel)
|
|
->setTitle('Motioner per år')
|
|
->setAnimated(true)
|
|
->withDataLabels();
|
|
|
|
$colors = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6'];
|
|
$colorIndex = 0;
|
|
|
|
foreach ($motionStats['by_year'] as $year => $count) {
|
|
$chart->addColumn($year, $count, $colors[$colorIndex % count($colors)]);
|
|
$colorIndex++;
|
|
}
|
|
|
|
return $chart;
|
|
}
|
|
|
|
#[Computed()]
|
|
public function motionTypePieChart()
|
|
{
|
|
$motionStats = $this->motionStatistics;
|
|
|
|
$chart = (new PieChartModel)
|
|
->setTitle('Motioner per typ')
|
|
->setAnimated(true)
|
|
->withDataLabels();
|
|
|
|
$colors = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444'];
|
|
$colorIndex = 0;
|
|
|
|
foreach ($motionStats['by_type'] as $type => $count) {
|
|
$chart->addSlice($type, $count, $colors[$colorIndex % count($colors)]);
|
|
$colorIndex++;
|
|
}
|
|
|
|
return $chart;
|
|
}
|
|
|
|
#[Computed()]
|
|
public function votingPieChart()
|
|
{
|
|
$votingStats = $this->votingStatistics;
|
|
|
|
$chart = (new PieChartModel)
|
|
->setTitle('Röstfördelning (urval av ledamöter)')
|
|
->setAnimated(true)
|
|
->withDataLabels();
|
|
|
|
$colors = [
|
|
'Ja' => '#10b981',
|
|
'Nej' => '#ef4444',
|
|
'Frånvarande' => '#6b7280',
|
|
'Avstår' => '#f59e0b',
|
|
];
|
|
|
|
foreach ($votingStats as $voteType => $count) {
|
|
$color = $colors[$voteType] ?? '#8b5cf6';
|
|
$chart->addSlice($voteType, $count, $color);
|
|
}
|
|
|
|
return $chart;
|
|
}
|
|
|
|
public function placeholder()
|
|
{
|
|
return view('livewire.person.show-skeleton');
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.party.show')
|
|
->title($this->party->label().' - Riksdagen App');
|
|
}
|
|
}
|