diff --git a/app/Livewire/Party/Index.php b/app/Livewire/Party/Index.php
new file mode 100644
index 0000000..ac079e1
--- /dev/null
+++ b/app/Livewire/Party/Index.php
@@ -0,0 +1,23 @@
+map(function ($party) {
+ return [
+ 'code' => $party->value,
+ 'name' => $party->label(),
+ 'logo' => $party->logo(),
+ ];
+ });
+
+ return view('livewire.party.index', compact('parties'))
+ ->title('Partier - Riksdagen App');
+ }
+}
diff --git a/app/Livewire/Party/Show.php b/app/Livewire/Party/Show.php
new file mode 100644
index 0000000..283ff0f
--- /dev/null
+++ b/app/Livewire/Party/Show.php
@@ -0,0 +1,229 @@
+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');
+ }
+}
diff --git a/resources/views/livewire/home-page.blade.php b/resources/views/livewire/home-page.blade.php
index 2a646ed..a225e10 100644
--- a/resources/views/livewire/home-page.blade.php
+++ b/resources/views/livewire/home-page.blade.php
@@ -123,6 +123,55 @@
+
+
+
+ Utforska partiernas motioner, ledamöter och röststatistik
+
+ Partier
+
+
- Utforska partier och deras ståndpunkter i olika frågor -
-Utforska information om de politiska partierna i Sveriges riksdag
+{{ $party['code'] }}
+ +{{ $party->value }}
+Ingen motionsstatistik tillgänglig
+ @endif +Ingen motionsstatistik tillgänglig
+ @endif +{{ $motion->undertitel }}
+ @endif +