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'); } }